what is the best way to create method like AfterInsert?

public void AfterInsert(MyEntity deleted, MyEntity inserted)
        {
            /// some code
            /// 
            /// deleted.Name =! inserted.Name
        }

        public void ModifyEntity(int id, string newName)
        {
            var deleted = Query.Single<MyEntity>(id);
            var inserted = Query.Single<MyEntity>(id);
            inserted.Name = newName;
            AfterInsert(deleted, inserted);
        }

Updated at 19.03.2010 7:32:40

In Session.Persiting / Session.Persisted i can just got time when session persist occurs.

I need to compare two states of entity "Before" and "After" (check wich properties changed and how much), in Session.Persiting / Session.Persisted I don't found any info about this.

More interesting is Session.EntityChanging with EntityEventArgs - but it occurs not on persisting, but on every field change.


Updated at 22.03.2010 7:26:45

Final goal is to write logic (like validators/constrains, but for whole entity) for checking integrity;

examples:

MyEntity : Entity
{
...

[Field]
public int MaxTextSize {get;set;}

[Field]
public string Text {get;set;} // - if Text.Length > MaxTextSize - throw Exception

...
}

MyEntity : Entity
{
...

[Field]
public ItemType{get;set;}

[Field]
public AnotherEntity LinkedEntity {get;set;} // - if (ItemType == 1 && LinkedEntity == null)  - throw Exception

...
}

MyEntity : Entity
{
...

[Field]
public ItemType{get;set;}

[Field]
public AnotherEntity LinkedEntity {get;set;} // - if (OLD.ItemType == 1 && NEW.Item == 2 && LinkedEntity == null)  - throw Exception

...
}

Updated at 22.03.2010 9:32:18

I see Object level validation rules, OnValidate() method but there is no OLD-values

I would like to create rule for "changing object type from 1 to 2 is available only when Link is not null", so I need values before changing object state.

Another problem is I would like to separate Data model from Business rules

This thread was imported from our support forum. The original discussion may contain more detailed answer.

asked Mar 18 '10 at 14:29

pil0t's gravatar image

pil0t
207575763


One Answer:

psulek wrote:

Take a look at Session.Current events like EntityCreated, EntityRemoveCompleted and so... more in events map...


Alex (Xtensive) wrote:

True. You can override Persistent.OnInitialize() method as well, if you need this in particular class.

And note that in case with DO there is no need to call Save()-like method. Instertions and other updates may be flushed at any moment of time after entity creation (and even during creation), so there is no such event. But you can be sure if persist has completed, all the changes that were previously unflushed are already there now.

So another good alternative is to track Session.Persiting / Session.Persiting events. Entity is inserted, if its PersistenceState is changing from New to Synchronized during persist operation.

And finally, Session.Persist() allows you to flush all the changes at any moment of time. Although it's not guaranteed DO won't do this by its own.


Alex (Xtensive) wrote:

There is Validation framework, that completely solves the problem.

See also: ValidationMode configuration option.


Alex (Xtensive) wrote:

The rule you descibed requires just one "old" value (e.g. ObjectType). If so, ideal way of enforcing it from the point of DO4 is to inherit from PropertyConstraintAspect (in Xtensive.Integrity.dll). The code must be:

[Serializable]
  public sealed class EmailConstraint : PropertyConstraintAspect
  {
    /// <inheritdoc/>
    public override bool CheckValue(IValidationAware target, object value)
    {
      var myEntity = (MyEntity) target;
      var newEntityType = (EntityType) value;
      var oldEntityType = (EntityType) GetPropertyValue(target);
      bool isValid = ... // custom validation logic here
      if (!isValid)
        base.CheckValue(target, value); // Will fail because of overriden method below, see http://goo.gl/0P9l
    }

    /// <inheritdoc/>
    public override bool CheckValue(object value)
    {
      return false; // Always fail
    }

    /// <inheritdoc/>
    public override bool IsSupported(Type valueType)
    {
      return valueType==typeof(EntityType);
    }

    /// <inheritdoc/>
    protected override string GetDefaultMessage()
    {
      return "[Write error message here, or read its localized version from resoucre]";
    }
  }

And in case with DO4 it's not a good idea to separate business logic from data: they are already separated. The data you deal with is actually stored not inside entities you use, but inside Session (there is a cache of EntityStates containing the data and changes made to it). So entities you deal with are designed to be business objects, not DTOs.

If you'd like to separate validation logic, you must plug into our validation API (by nearly the same way).

answered Mar 18 '10 at 19:13

Editor's gravatar image

Editor
46154156157

Alex Kofman wrote: You can subscribe on Session.EntityChanging or Session.EntityFieldValueSetting event, get data interesting for you and store it somewhere. Then you can use this data on persisting stage. For example you can store such data in Session.Extensions.

(Mar 18 '10 at 19:13) Editor Editor's gravatar image

Possibly, more important question is: "What is your final goal / intention?".

E.g. if you're going to serialize these changes to repeat them, there is a ready-and-working Operations framework for this.

(Mar 18 '10 at 19:13) Alex Yakunin Alex%20Yakunin's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×573

Asked: Mar 18 '10 at 14:29

Seen: 1,614 times

Last updated: Mar 18 '10 at 14:29

powered by OSQA