Is it possible perform actions in POCO before inse

2019-05-30 09:30发布

Let's assume this Entity Framework sample:

public class User
{ 
    public int UserID { get; set; } 
    public string Name { get; set; }      
} 

public class MyDbContext : DbContext 
{ 
    public DbSet<User> Users { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
        using (var db = new MyDbContext ()) 
        {     
            var user = new User { Name = "Foo"}; 
            db.Users.Add(user); 
            db.SaveChanges();      

            Console.WriteLine("Press any key to exit..."); 
            Console.ReadKey(); 
        } 
    } 
}

I want add to User class events, like "BeforeInsert" or "BeforeUpdate", and when the code...

db.Users.Add(user); 

... is executed anywhere in the application, the "BeforeInsert" method will be raised. Is it possible?

2条回答
劳资没心,怎么记你
2楼-- · 2019-05-30 09:45

@JC's answer is correct. I will just show code, in which you can do what you want. First of all, override SaveChanges method in your context, and call this overriden SaveChanges method: context.SaveChanges(true) instead of conntext.SaveChanges()

public class MyDbContext : DbContext 
{ 
    public DbSet<User> Users { get; set; } 

    public int SaveChanges(bool performCustomOperations)
    {
        if(performCustomOperations)
        {
            CustomContextManager contextManager = new CustomContextManager(this);
            //Perform operations you want before saving data
            contextManager.PerformBeforeUpdate();

            //To do: Add your own PerformBeforeInsert method to CustomContextManager class
        }

        //Save changes to underlying database
        this.SaveChanges();
    }
} 

Your CustomContextManager class should look like this. Performing your before update operations in PerformBeforeUpdate method. You can add your own PerformBeforeInsert and/or PerformBeforeDelete methods.

public class CustomContextManager
{
    private MyDbContext context;

    public CustomContextManager(MyDbContext contextParam)
    {
        if (contextParam == null)
            throw new ArgumentNUllException(nameof(contextParam));

        this.context = contextParam;
    }

    public void PerformBeforeUpdate
    {
        //Get object context to be able to perform operations
        System.Data.Objects.ObjectContext myObjectContext =
            ((IObjectContextAdapter)context).ObjectContext;

        IEnumerable<ObjectStateEntry> updatedRecords =
            taxesObjectContext.ObjectStateManager.GetObjectStateEntries(
            System.Data.EntityState.Modified);

        if (updatedRecords != null
            && updatedRecords.Count() > 0)
        {
            foreach (ObjectStateEntry stateEntry in updatedRecords)
            {
                if (stateEntry != null
                    && stateEntry.Entity != null)
                {
                    //Do what operations you want instead of below linnes
                    User modifiedUser = stateEntry.Entity as User;
                    if(modifiedUser != null)
                        modifiedUser.Name = "Altered before update";
                }
            }
        }
    }
}
查看更多
迷人小祖宗
3楼-- · 2019-05-30 09:55

You want to do that in an override of the SaveChanges() method of your DbContext. Scan through the ChangeTracker.Entries collection for any entries of your type. Then for each of those, do your BeforeInsert or BeforeUpdate operations based on whether entry.State is EntityState.Added or EntityState.Modified.

查看更多
登录 后发表回答