问题
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?
回答1:
@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";
}
}
}
}
}
回答2:
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.
来源:https://stackoverflow.com/questions/28576033/is-it-possible-perform-actions-in-poco-before-insert-update