1

リポジトリと作業単位のパターンを使用して、基になる永続ストア(MS SQL Server 2012)にオブジェクトを追加するときに問題が発生します。問題は、コミットされると、生成される挿入ステートメントの順序が間違った順序になり、外部キーの制約のために失敗することです。

注文ラインを使用して顧客、住所、アカウント、注文を一度に作成したいとします(1回のコミット)。

using (var tx = new TransactionScope())
{
    var address = new Address(...);
    _addressRepository.Add(address);

    var customer = new Customer(...);
    customer.AssignLegalAddress(address.Id);
    _customerRepository.Add(customer);

    var account = new Account(..., customer.Id);
    _accountRepository.Add(account);

    var order = new Order();
    order.AssignBuyerAccount(account.Id);
    order.AddOrderLine(...);
    order.AddOrderLine(...);

    _orderRepository.Add(order);

    _unitOfWork.Commit();
    tx.Complete();
}

したがって、顧客がコミットされるためには、アドレスが最初にコミットされ、顧客がアカウントの前に、最後にアカウントが注文の前にコミットされる必要があります。したがって、さまざまなリポジトリでAddを呼び出す順序。

上記のリポジトリは、最初に以下のEntity Framework 5.0コードを使用し、各追加操作は、基になるDbContextにエンティティを追加することになります。これを次のように翻訳できますDbContext.Set<TEntity>().Add(entity)。Commitの呼び出しは、基本的にDbContext.SaveChanges()を呼び出します。

問題は、EFが追加された順序を気にしないように見えることです。Commitで基になるストアに送信されたクエリを監視していると、最初にアドレスが作成され、これまでのところ良好であることがわかりますが、次にアカウントを作成するための挿入ステートメントが実行されます。顧客がまだ作成されていないため、これは失敗します。

変更を保存するときに、EFに追加された順序を考慮に入れる方法はありますか?それ以外の場合は、次のように手動で変更をコミットする必要があります。

using (var tx = new TransactionScope())
{
    var address = new Address(...);
    _addressRepository.Add(address);

    _unitOfWork.Commit();

    var customer = new Customer(...);
    customer.AssignLegalAddress(address.Id);
    _customerRepository.Add(customer);

    _unitOfWork.Commit();

    var account = new Account(..., customer.Id);
    _accountRepository.Add(account);

    _unitOfWork.Commit();

    var order = new Order();
    order.AssignBuyerAccount(account.Id);
    order.AddOrderLine(...);
    order.AddOrderLine(...);

    _orderRepository.Add(order);

    _unitOfWork.Commit();
    tx.Complete();
}

しかし、それはほとんど最適な解決策のようには思えません。何か案は?

4

1 に答える 1

0

エンティティを挿入する場合、EF はグラフ全体を挿入します。

// Build graph
var customer = new Customer(...);
customer.LegalAddress = new Address(...);
var account = new Account();
account.Customer = customer;
var order = new Order();
order.BuyerAccount = account;
// Here all Navigation properties updated
// and state of all entities set to Added
_orderRepository.Add(order); 
// Here all entities inserted in transaction, PK and FK updated
context.SaveChanges();

複雑さは、グラフの一部だけを挿入する必要がある場合に始まります。次に、グラフ内のエンティティの状態を手動で設定する必要があります。

于 2013-03-20T09:36:06.547 に答える