导航属性和查找实体

本文关键字:实体 查找 属性 导航 | 更新日期: 2023-09-27 18:18:24

我有一个代码优先的实体,看起来像这样:

public class Account
{
    public Guid Id { get; set; }
    public int AccountTypeId { get; set; }
    [ForeignKey("AccountTypeId")]
    public virtual AccountType AccountType { get; set; }
}

AccountType是一个被视为只读的查找表。我们永远不会想要修改它。

当我查询一个帐户时,AccountTypeIdAccountType都用数据库中的正确值填充。但是,当更新这两个属性中的任何一个时,另一个属性不会得到更新,直到我们调用SaveChanges()访问服务器。我们不想在早期点击服务器来保存东西,并且对于实体的一些单元测试,我们不能依赖于对dbContext.SaveChanges()方法的调用,所以我们覆盖了导航属性以从离线集合中获取其值,如下所示:

public class Account
{
    public Guid Id { get; set; }
    public int AccountTypeId { get; set; }
    [ForeignKey("AccountTypeId")]
    public virtual AccountType AccountType
    {
        get
        {
            return AccountTypeCollection.GetById(this.FormatTypeId);
        }
        set
        {
            this.AccountTypeId = (value ?? AccountTypeCollection.None).Id;
        }
    }
}

这样,我们仍然可以在LINQ查询中使用AccountType导航属性,并确保它始终与AccountTypeId同步。然而,我们发现的问题是,在某些情况下,我们会受到很大的性能影响。例如,当我们从与Account有关系的Transaction实体获得数百个交易并试图修改一个时,EF试图将所有数百个帐户记录保存在数据库中,因为它认为他们的AccountType发生了变化!为什么会发生这种情况?我们如何预防它?

如果我们取消AccountType与[NotMapped]的映射,那么这将不会发生。但是不能再在任何LINQ-to-Entity查询中参与此属性。

我们是否可以使用离线c#集合中的查找表,并且仍然能够在LINQ-to-Entities中使用它们而不会出现这些问题?枚举类型的限制太大,不能扩展。正确的做法是什么?

谢谢!

导航属性和查找实体

您可以通过覆盖 SaveChanges 来取消所有修改过的AccountType

public class YourContext : DbContext
{
    // dbsets
    public override int SaveChanges()
    {
        var entries = ChangeTracker.Entries<AccountType>()
            .Where(at => at.State == EntityState.Modified);
        foreach (var entry in entries)
        {
            entry.State = EntityState.Unchanged;
        }
        return base.SaveChanges();
    }
}

应用程序中所有修改的AccountType将不会更新到数据库