我覆盖了DbContext.SaveChanges(),以便在我的应用程序中实现数据库审计。
我的DbContext类看起来像这样:
public override int SaveChanges()
{
throw new InvalidOperationException("User Id must be provided for auditing purposes.");
}
public int SaveChanges(bool suppressAudit)
{
if (suppressAudit)
return base.SaveChanges();
else
throw new InvalidOperationException("User Id must be provided for auditing purposes.");
}
public int SaveChanges(int userId)
{
foreach(var entity in ChangeTracker.Entries().Where(p=>p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified))
{
foreach(var auditEntry in GetAuditRecordsForChange(entity,userId))
{
Audit.Add(auditEntry);
}
}
return base.SaveChanges();
}
期间"正常"我的应用程序的操作似乎工作得非常好(至少到目前为止)。
但是,当我想使用初始化程序重新创建数据库时出现问题,如下所示:
public class ABS4Initializer : DropCreateDatabaseAlways<MyContext>
{
protected override void Seed(MyContext context)
{
var users = BuildUserData();
users.ForEach(u => context.Users.AddOrUpdate(u));
context.SaveChanges(true);
}
}
尽管我在种子中使用了context.SaveChanges(true)
调用,某些地方正在调用context.SaveChanges()
(因此,会抛出预期的异常)
我怀疑它围绕着数据库/表格的创建,但我找不到它。
在SaveChanges
上坚持一个断点只会显示&#34;外部代码&#34;正在打电话:
我假设我在某个地方错过了一些覆盖,或者甚至更简单/愚蠢的事情。
任何线索?
(作为参考,我试图实现类似于此问题的最高投票答案的内容:how to create an audit trail with Entity framework 5 and MVC 4)
修改 根据注释中的要求,这是一个产生相同结果的FULL dbContext类:
public class DemoContext : DbContext
{
public DemoContext() : base("DemoContext")
{
}
public DbSet<User> Users { get; set; }
public DbSet<AuditLog> Audit { get; set; }
public override int SaveChanges()
{
throw new InvalidOperationException("User Id must be provided for auditing purposes.");
}
public int SaveChanges(bool suppressAudit)
{
if (suppressAudit)
return base.SaveChanges();
else
throw new InvalidOperationException("User Id must be provided for auditing purposes.");
}
public int SaveChanges(int userId)
{
foreach (var entity in ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified))
{
foreach (var auditEntry in GetAuditRecordsForChange(entity, userId))
{
Audit.Add(auditEntry);
}
}
return base.SaveChanges();
}
private List<AuditLog> GetAuditRecordsForChange(DbEntityEntry dbEntity, int userId)
{
return new List<AuditLog>();
}
}
的App.config
<entityFramework>
<contexts>
<context type="DAL.DAL.DemoContext, DAL">
<databaseInitializer type="DAL.DAL.ABS4Initializer, DAL"/>
</context>
</contexts>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
答案 0 :(得分:1)
Entity Framework中的DropCreateDatabaseAlways()类具有以下虚拟方法InitializeDatabase,如果您下载EF源代码,您会发现实现是这样的:
public virtual void InitializeDatabase(TContext context)
{
Check.NotNull(context, "context");
context.Database.Delete();
context.Database.Create(DatabaseExistenceState.DoesNotExist);
Seed(context);
context.SaveChanges();
}
您需要覆盖以下内容:
public override void InitializeDatabase(ABSContext context)
{
if (context != null)
{
if (context.Database.Exists())
{
context.Database.Delete();
}
context.Database.Create();
Seed(context);
context.SaveChanges(true);
}
else
throw new ArgumentNullException();
}