リポジトリと作業単位のパターンを使用して、基になる永続ストア(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();
}
しかし、それはほとんど最適な解決策のようには思えません。何か案は?