5

別の投稿で、いつ使用するかについて説明を求めましたDbSet<TEntity>.Local。まだ回答がありません。質問に情報が多すぎるのではないかと思います。もう少し深く掘り下げた後、私はより具体的な質問をすることができます。

うまくいけば、皆さんは私のシナリオで2つのオプションのどちらを選択するかを説明できます。

何を達成したいですか?

  1. からエンティティを取得しようとしていますRepository。エンティティはまだ「追加」状態です(つまり、まだメソッドを呼び出していませんSaveChanges)。これが必要なのは、エンティティを1つのアトミックアクションに格納したいので、完全なモデルを検証するまで呼び出しを延期する必要があるためですSaveChanges

  2. さらに、遅延読み込みナビゲーションプロパティに拡張メソッド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

よろしくお願いします!

4

1 に答える 1

5

それは本当にあなたが何をしたいかによって異なります。あなたのコードは具体的にフィルタリングされDbEntityEntry.Stateていないので、コンテキストによって追跡されるすべてのエンティティが追加された状態にあると確信していると思います。

追跡されたすべてのエンティティが追加された状態にあると確信できない場合は、 sChangeTrackerをフィルタリングしてから、実際のエンティティへの参照を取得して作業することができます。DbEntityEntryEntityState.Added

エンティティ自体Localを取得すると。ObservableCollection<T>それらがすべて追加された状態にあると確信している場合は、これがおそらく最も簡単です。確信が持てない場合は、コレクションを列挙しDbEntityEntry、コンテキストから を取得して確認する必要があります。

foreach(var entity in collection)
{
  if(context.entry(entity).State == EntityState.Added)
  {
  //do stuff...
  }
}

これが検証を実行するためのすべてである場合は、他の方法でそれを行うことができます。そのいくつかはここで読むことができます。

于 2013-02-27T01:35:42.460 に答える