別の投稿で、いつ使用するかについて説明を求めましたDbSet<TEntity>.Local
。まだ回答がありません。質問に情報が多すぎるのではないかと思います。もう少し深く掘り下げた後、私はより具体的な質問をすることができます。
うまくいけば、皆さんは私のシナリオで2つのオプションのどちらを選択するかを説明できます。
何を達成したいですか?
からエンティティを取得しようとしています
Repository
。エンティティはまだ「追加」状態です(つまり、まだメソッドを呼び出していませんSaveChanges
)。これが必要なのは、エンティティを1つのアトミックアクションに格納したいので、完全なモデルを検証するまで呼び出しを延期する必要があるためですSaveChanges
。さらに、遅延読み込みナビゲーションプロパティに拡張メソッド
Include
を使用する依存コードがあるため、IQueryableインターフェイスに準拠する必要があります。Queryable
私は何を試しましたか?
過去数日間でたくさんのことがありましたが、要約すると、次の2つの異なるアプローチになります。
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 = "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
?
よろしくお願いします!