导航属性和查找实体

时间:2014-08-17 02:49:05

标签: c# entity-framework

我有一个Code First实体,如下所示:

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同步。然而,我们发现的问题是,在某些情况下,我们会获得很高的性能。例如,当我们从与Transaction有关系的Account实体获得一百个事务并尝试修改一个时,EF会尝试将所有数百个帐户记录保存在数据库中,因为它认为他们的AccountType已经改变了!为什么会这样?我们怎样才能阻止它?

如果我们使用[NotMapped]取消映射AccountType,则不会发生这种情况。但是,不能再将此属性参与任何LINQ-to-Entity查询。

我们有什么方法可以使用离线C#集合中的查找表,并且仍然可以在没有这些问题的LINQ到实体中使用它们吗?枚举类型太有限,无法扩展。什么是正确的方法?

谢谢!

1 个答案:

答案 0 :(得分:0)

您可以通过覆盖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都不会更新到数据库。