我有一个Code First实体,如下所示:
public class Account
{
public Guid Id { get; set; }
public int AccountTypeId { get; set; }
[ForeignKey("AccountTypeId")]
public virtual AccountType AccountType { get; set; }
}
AccountType
是一个查找表,被视为只读。我们永远不会想要修改它。
当我查询帐户时,AccountTypeId
和AccountType
都会使用数据库中的正确值填充。但是,在更新这些属性中的任何一个时,在我们调用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到实体中使用它们吗?枚举类型太有限,无法扩展。什么是正确的方法?
谢谢!
答案 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
都不会更新到数据库。