在 different post 中,我要求澄清何时使用 DbSet<TEntity>.Local
。我还没有得到答案,我认为这个问题可能包含太多信息。在深入挖掘之后,我可以问一个更具体的问题。
希望你们能解释在我的场景中选择两个选项中的哪一个。
我想要达到什么目标?
Repository
中检索实体。实体仍处于“添加”状态(即我还没有调用 SaveChanges
方法)。我需要这个,因为我想将实体存储在一个原子操作中,所以我必须将 SaveChanges
调用推迟到我验证完整模型之后。 Include
上的扩展方法 Queryable
来延迟加载导航属性的依赖代码。 我尝试了什么?
过去几天的事情很多,但归结为以下两种不同的方法:
DbSet<TEntity>.Local
属性 DbContext.ChangeTracker
可视化不同方法的代码示例
public void AddAndRetrieveUncommittedEntityFromDbContext()
{
Database.SetInitializer(new DropCreateDatabaseAlways<TestContext>());
var testContext = new TestContext();
// Initialize the entities and store them in the repository
var tenant = new Tenant { Name = "test", Guid = Guid.NewGuid().ToString() };
var user = new User { Name = "bas", EmailAddress = "[email protected]", Password = "password" };
tenant.Users.Add(user);
testContext.Tenants.Add(tenant);
// NOTE: I did not call `SaveChanges` yet, but still I want to retrieve
// the tenant from my repository
///////////////////////////////////////////////
// Alternative one, use the ChangeTracker... //
///////////////////////////////////////////////
IEnumerable<DbEntityEntry<Tenant>> tenants = testContext.ChangeTracker.Entries<Tenant>();
IQueryable<Tenant> query = tenants.Select(dbEntityEntry => dbEntityEntry.Entity).AsQueryable();
Tenant storedTenant = query.
Where(ent => ent.Name.Equals("test")).
Include(ent => ent.Users).First();
Assert.IsNotNull(storedTenant.Users.FirstOrDefault());
// hurray, it passes
///////////////////////////////////////////////
// Alternative two, use the 'Local' property //
///////////////////////////////////////////////
IQueryable<Tenant> query2 = testContext.Tenants.Local.AsQueryable();
Tenant storedTenant2 = query2.
Where(ent => ent.Name.Equals("test")).
Include(ent => ent.Users).First();
Assert.IsNotNull(storedTenant2.Users.FirstOrDefault());
// hurray, it passes
////////////////////////////////////////////////
// For completeness => entity is not in DbSet //
////////////////////////////////////////////////
IQueryable<Tenant> query3 = testContext.Tenants.AsQueryable();
Tenant storedTenant3 = query3.
Where(ent => ent.Name.Equals("test")).
Include(ent => ent.Users).FirstOrDefault();
Assert.IsNotNull(storedTenant3);
// Fails, because the entity is not yet available in the DbSet 'testContext.Tenants'
}
testContext 非常简单:
public class TestContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Tenant> Tenants { get; set; }
public TestContext() : base("Test1") {}
}
问题
DbSet<TEntity>.Local
和 ChangeTracker
的优缺点是什么? 非常感谢提前!
最佳答案
这真的取决于你想做什么。您的代码都没有专门通过 DbEntityEntry.State
过滤,因此我假设您确定上下文跟踪的所有实体都处于添加状态。
如果您不确定所有跟踪的实体都处于添加状态,那么 ChangeTracker
使您有机会通过 DbEntityEntry
过滤 EntityState.Added
s,然后获取对实际实体的引用以进行处理。
使用 Local
您可以获得实体本身的 ObservableCollection<T>
。如果您确定它们都处于添加状态,那么这可能是最简单的。如果您不确定,那么您必须枚举集合并从上下文中获取 DbEntityEntry
以确保:
foreach(var entity in collection)
{
if(context.entry(entity).State == EntityState.Added)
{
//do stuff...
}
}
如果这就是执行验证的全部内容,那么还有其他方法可以进行,其中一些可以读取 here 。
关于c# - DbSet<TEntity>.Local 与 DbContext.ChangeTracker,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15101196/