bas*_*bas 12 c# entity-framework dbcontext dbset
几天来,我一直在努力从存储库(DbContext)中检索我的实体.
我试图在原子动作中保存所有实体.因此,不同的实体一起代表了我的一些有价值的东西.如果所有实体都是"有效",那么我可以将它们全部保存到数据库中.实体"a"已存储在我的存储库中,需要检索以"验证"实体"b".
这就是问题出现的地方.我的存储库依赖于DbSet<TEntity>与Linq2Sql一起工作的类(Include()例如导航属性).但是,DbSet<TEntity>它不包含处于"已添加"状态的实体.
所以我(据我所知)有两个选择:
ChangeTracker以查看哪些实体可用,并根据它们将它们查询到一个集合中EntityState.DbSet<TEntity>.Local属性.这ChangeTracker似乎涉及一些额外的努力工作,以使我可以使用Linq2Sql Include()导航属性,例如
在DbSet<TEntity>.Local似乎有点怪我.它可能只是名字.我只是读了一些表现不佳的东西(比DbSet <>本身慢).不确定这是否是虚假陈述.
具有重要EntityFramework经验的人能否对此有所启发?什么是"明智"的道路?或者我看到了幽灵,我应该总是使用这个.Local属性吗?
使用代码示例更新:
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?
}
Run Code Online (Sandbox Code Playgroud)
Repository在我的Repository我有这个方法:
public IQueryable<TEntity> GetAll()
{
return Context.Set<TEntity>().AsQueryable();
}
Run Code Online (Sandbox Code Playgroud)
我以这种方式在业务代码中使用它:
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();
}
Run Code Online (Sandbox Code Playgroud)
这主要是我更喜欢坚持DbSet变量的原因.我需要灵活的Include导航属性.如果我使用ChangeTracker我检索a中的实体List,这不允许我在稍后的时间点延迟加载相关的实体.
如果这接近难以理解的崩溃*,请告诉我,以便我可以改进这个问题.我迫切需要一个答案.
很多提前!
Ter*_*tta 14
如果您希望能够"轻松"对DbSet发出查询并让它找到新创建的项目,那么您需要在创建每个实体后调用SaveChanges().如果您使用"工作单元"样式方法来处理持久性实体,这实际上没有问题,因为您可以让工作单元将UoW中的所有操作包装为数据库事务(即,当UoW创建新的TransactionScope时创建,并在UoW完成时调用Commit()).使用此结构,更改将发送到DB,并且对DbSet可见,但对其他UoW不可见(以您使用的任何隔离级别为模).
如果你不想要这个开销,那么你需要修改你的代码以在适当的时候使用Local(这可能涉及查看Local,然后如果你没找到你的话就发出对DbSet的查询)正在寻找).在这些情况下,DbSet上的Find()方法也非常有用.它将通过Local或DB中的主键查找实体.因此,如果您只需要通过主键查找项目,这非常方便(并且还具有性能优势).
正如 Terry Coatta 所提到的,如果您不想先保存记录,最好的方法是检查两个来源。
例如:
public Person LookupPerson(string emailAddress, DateTime effectiveDate)
{
Expression<Func<Person, bool>> criteria =
p =>
p.EmailAddress == emailAddress &&
p.EffectiveDate == effectiveDate;
return LookupPerson(_context.ObjectSet<Person>.Local.AsQueryable(), criteria) ?? // Search local
LookupPerson(_context.ObjectSet<Person>.AsQueryable(), criteria); // Search database
}
private Person LookupPerson(IQueryable<Person> source, Expression<Func<Person, bool>> predicate)
{
return source.FirstOrDefault(predicate);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10136 次 |
| 最近记录: |