gpt4 book ai didi

c# - DbSet.Local 与 DbContext.ChangeTracker

转载 作者:行者123 更新时间:2023-11-30 16:19:36 25 4
gpt4 key购买 nike

different post 中我要求澄清何时使用 DbSet<TEntity>.Local .我还没有得到答案,我认为这个问题可能包含太多信息。在深入挖掘之后,我可以提出一个更具体的问题。

希望你们能解释一下在我的场景中应该选择两个选项中的哪一个。

我想达到什么目的?

  1. 我正在尝试从我的 Repository 中检索实体.实体仍处于“已添加”状态(即我尚未调用 SaveChanges 方法)。我需要这个,因为我想将实体存储在一个原子操作中,所以我必须推迟 SaveChanges调用直到之后我验证了完整的模型。

  2. 此外,我还需要符合 IQueryable 接口(interface),因为我有使用扩展方法的依赖代码 IncludeQueryable延迟加载导航属性。

我尝试了什么?

过去几天发生了很多事情,但归结为以下两种不同的方法:

  • 通过 DbSet<TEntity>.Local 检索处于“已添加”状态的实体属性(property)
  • 通过 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 = "bas@domain.com", 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让您有机会过滤 DbEntityEntryEntityState.Added然后获取对要处理的实际实体的引用。

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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com