几天来,我一直在努力从存储库 (DbContext
) 中检索我的实体。
我正在尝试将所有实体保存在一个原子操作中。因此,不同的实体一起代表对我有值(value)的东西。如果所有实体都是“有效”的,那么我可以将它们全部保存到数据库中。实体“a”已存储在我的存储库中,需要检索以“验证”实体“b”。
这就是问题所在。我的存储库依赖于 DbSet<TEntity>
与 Linq2Sql 一起工作的类(Include()
导航属性,例如)。但是,DbSet<TEntity>
不包含处于“已添加”状态的实体。
所以我(据我所知)有两个选择:
- 使用
ChangeTracker
查看哪些实体可用并根据其EntityState
将它们查询到一个集合中. - 使用
DbSet<TEntity>.Local
属性(property)。
ChangeTracker
似乎需要一些额外的努力才能让它以某种方式工作,这样我就可以使用 Linq2Sql 来 Include()
导航属性,例如
DbSet<TEntity>.Local
我觉得有点奇怪。这可能只是名字。我刚刚读到一些它表现不佳的东西(比 DbSet<> 本身慢)。不确定这是否是错误的陈述。
有 EntityFramework 丰富经验的人能对此有所启发吗?什么是“明智”的道路?还是我看到了鬼魂,我是否应该始终使用 .Local
属性(property)?
更新代码示例:
错误示例
public void AddAndRetrieveUncommittedTenant()
{
_tenantRepository = new TenantRepository(new TenantApplicationTestContext());
const string tenantName = "testtenant";
// Create the tenant, but not call `SaveChanges` yet until all entities are validated
_tenantRepository.Create(tenantName);
//
// Some other code
//
var tenant = _tenantRepository.GetTenants().FirstOrDefault(entity => entity.Name.Equals(tenantName));
// The tenant will be null, because I did not call save changes yet,
// and the implementation of the Repository uses a DbSet<TEntity>
// instead of the DbSet<TEntity>.Local.
Assert.IsNotNull(tenant);
// Can I safely use DbSet<TEntity>.Local ? Or should I play
// around with DbContext.ChangeTracker instead?
}
我想如何使用我的 Repository
的示例
在我的 Repository
我有这个方法:
public IQueryable<TEntity> GetAll()
{
return Context.Set<TEntity>().AsQueryable();
}
我以这种方式在业务代码中使用:
public List<Case> GetCasesForUser(User user)
{
return _repository.GetAll().
Where(@case => @case.Owner.EmailAddress.Equals(user.EmailAddress)).
Include(@case => @case.Type).
Include(@case => @case.Owner).
ToList();
}
这主要是我更喜欢坚持 DbSet
的原因像变量。我需要灵 active Include
导航属性。如果我使用 ChangeTracker
我在 List
中检索实体,这不允许我在以后的某个时间延迟加载相关实体。
如果这接近于难以理解的废话*t,那么请告诉我,以便我改进问题。我迫切需要一个答案。
提前致谢!
最佳答案
如果您希望能够“轻松地”对 DbSet 发出查询并让它找到新创建的项目,那么您需要在创建每个实体后调用 SaveChanges()。如果您使用“工作单元”风格的方法来处理持久实体,这实际上没有问题,因为您可以让工作单元将 UoW 中的所有操作包装为 DB 事务(即,在 UoW 时创建一个新的 TransactionScope被创建,并在 UoW 完成时对其调用 Commit())。使用此结构,更改将发送到数据库,并且对 DbSet 可见,但对其他 UoW 不可见(模数您使用的任何隔离级别)。
如果您不想要这样的开销,那么您需要修改代码以在适当的时候使用 Local(这可能涉及查看 Local,然后如果您不希望使用 Local,则对 DbSet 发出查询找到你要找的东西)。 DbSet 上的 Find() 方法在这些情况下也非常有用。它将通过主键在本地或数据库中找到一个实体。所以如果你只需要通过主键定位项目,这非常方便(并且具有性能优势)。
关于c# - DbSet<>.Local 是否需要特别小心使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15094903/