2

コミットされていないエンティティをDbContextから取得するにはどうすればよいですか?

次のテストを検討してください。

    [Test]
    public void AddAndRetrieveUncommittedTenant()
    {
        _tenantRepository.Create("testtenant");
        var tenant = _tenantRepository.GetTenantByName("testtenant");

        Assert.AreEqual("testtenant", tenant.Name);
    }

tenantであるため、テストは失敗しますnull

間には特定のビジネスコードがたくさんありますが、要約すると次のようになります。

私のRepositoryクラスGetTenantByNameでは、最後のメソッドがメソッドを呼び出しますGetAll

    public IQueryable<TEntity> GetAll()
    {
        return DbSet.AsQueryable();
    }

    private IDbSet<TEntity> DbSet
    {
        get { return Context.Set<TEntity>(); }
    }

そして、私を拡張するクラスDbContextには、次のメソッドがあります。

    public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
    {
        return base.Set<TEntity>();
    }

ブレークポイントを設定するreturn base.Set<TEntity>();と、エンティティがリポジトリで(localプロパティを介して)利用可能であることがわかります。


ここに画像の説明を入力してください


コミットされていないエンティティをリポジトリから取得するにはどうすればよいですか?

4

2 に答える 2

4

派生したクラスを使用しDbContext、次のメソッドを追加して、変更されたエンティティにアクセスします。これにより、で変更されたエンティティにアクセスする方法もわかりますDbContext

public virtual IEnumerable<DbEntityEntry> ChangedEntities
{
    get { return base.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged); }
}

ChangeTrackerはのパブリックプロパティでDbContextあるため、外部クラスからもこのプロパティにアクセスできます。

var dirtyEntities = myDbContext.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged);

または、追加/変更されたエンティティなどを検索する場合は、より具体的にすることができます。

var addedEntities = myDbContext.ChangeTracker.Entries().Where(e => e.State == EntityState.Added);
var modifiedEntities = myDbContext.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified);

等々。

于 2013-02-25T18:22:15.383 に答える
2

以下の簡単なトランザクションと同じように実行します。

using (var scope = new TransactionScope(TransactionScopeOption.Required,
                        new TransactionOptions()
                        {
                            IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
                        }))
{
    var employees = _context.Employees.ToList();
    scope.Complete();
}

データを同期的にフェッチする場合は、上記のコードにTransactionScopeAsyncFlowOption.Enabledを追加します。

using (var scope = new TransactionScope(TransactionScopeOption.Required,
                        new TransactionOptions()
                        {
                            IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
                        },
                        TransactionScopeAsyncFlowOption.Enabled))
{
    var employees = await _context.Employees.ToListAsync();
    scope.Complete();
}

簡単にするために、上記のトランザクションに対して独自の拡張メソッドを使用できます。

public static async Task<List<T>> ToListWithNoLockAsync<T>(this IQueryable<T> query, CancellationToken cancellationToken = default)
{
    List<T> result = default;
    using (var scope = new TransactionScope(TransactionScopeOption.Required,
                            new TransactionOptions()
                            {
                                IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
                            },
                            TransactionScopeAsyncFlowOption.Enabled))
    {
        result = await query.ToListAsync(cancellationToken);
        scope.Complete();
    }
    return result;
}

以下のように簡単に使用できます。

var employees = dbContext.Employees
                          .AsNoTracking()
                          .Where(a => a.IsDelete == false)
                          .ToListWithNoLockAsync();
于 2020-12-20T08:36:51.637 に答える