【问题标题】:How can I associate an object that will be inserted into the database with one that has not yet been inserted using Entity Framework?如何将要插入数据库的对象与尚未使用 Entity Framework 插入的对象相关联?
【发布时间】:2013-09-22 19:44:14
【问题描述】:

我正在尝试按照这篇文章http://jmdority.wordpress.com/2011/07/20/using-entity-framework-4-1-dbcontext-change-tracking-for-audit-logging/ 在我的 MVC 4 中使用 EF 应用程序实施审计。

我有一个继承自 DbContext 并覆盖 SaveChanges 方法的类。在这个新的 SaveChanges 方法中,我将一条记录插入到审计表中。

可以被审计的实体:

public class Fruit
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long FruitId{ get; set; }

    public string FruitName{ get; set; }
}

以及 FruitAudit 表的模型:

public class FruitAudit
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long FruitAuditId{ get; set; }

    public long FruitId{ get; set; }

    // Auditing properties like modifying user and timestamps.
}

还有我重写的 SaveChanges 方法:

public int SaveChanges()
{
    var entriesToAudit = this.ChangeTracker.Entries().Where(p =>
        (p.State == System.Data.EntityState.Added || p.State == System.Data.EntityState.Deleted || p.State == System.Data.EntityState.Modified);

    foreach (var entity in entriesToAudit)
    {
        using (var context = new StoreContext())
        {
            Fruit fruit = entity.Entity as Fruit;
            FruitAudit audit = new FruitAudit()
            {
                FruitId = Fruit.FruitId;
                // Other auditing properties set here
            }
            context.FruitAudits.Add(audit);
            context.SaveChanges();
        }
    }

    return base.SaveChanges();
}

插入 Fruit 时发生错误,因为在尝试保存 FruitAudit 记录时尚未设置 FruitId。 FruitId 是从数据库自动生成的,但实际的 Fruit 对象在插入审计记录之后才会保存。如何将此 FruitAudit 与插入的 Fruit 关联?

【问题讨论】:

    标签: entity-framework asp.net-mvc-4


    【解决方案1】:

    我建议使用FruitAudit 的虚拟导航属性,这样您就有了类似的东西:

    public class FruitAudit
    {
        public int FruitAuditId { get; set; }
    
        public int FruitId { get; set; }
        public virtual Fruit Fruit { get; set; }
    }
    

    你的Fruit 看起来像:

    public class Fruit
    {
        public int FruitId { get; set; }
    
        public string FruitName { get; set; }
    }
    

    然后,当您转到SaveChanges() 时,您只需说:

    Fruit fruit = entity.Entity as Fruit;
    FruitAudit audit = new FruitAudit()
    {
      Fruit = fruit;
      // Other auditing properties set here
    }
    
    ...
    
    context.Fruits.Add(fruit);
    context.FruitAudits.Add(audit);
    

    【讨论】:

    • 如果我的所有对象更改都有关联的审核,但其中一些没有,则此方法有效。在这种情况下,我需要将它们添加到 base.SaveChanges() 中。但是,当我在审核期间已经保存了更改时,该调用会失败。有什么想法吗?
    • 您也可以覆盖 BeforeSaveChanges。很难理解你的场景,但如果你有多个这样的条件,也许它会有一些用处。
    【解决方案2】:

    我最终制作了所有实体更改的副本,然后调用 base.SaveChanges()。这将插入所有的水果。然后我检查实体更改的副本并为每个更改插入审计记录。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-21
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 2020-11-05
      相关资源
      最近更新 更多