DropCreateDatabaseAlways with overriden context.SaveChanges()

时间:2015-06-09 09:55:43

标签: c# entity-framework

我覆盖了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;正在打电话: Call Stack

我假设我在某个地方错过了一些覆盖,或者甚至更简单/愚蠢的事情。

任何线索?

(作为参考,我试图实现类似于此问题的最高投票答案的内容: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>

1 个答案:

答案 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();
        }