4つのデータベーステーブルの挿入と2つの更新をカプセル化するトランザクションを作成しようとしています。
私は「ほとんど」働いています。つまり、これらの6 dBの相互作用のいずれかでエラーが発生した場合、最初のロールバックを除いて、以前のロールバックが発生します。最初はヘッダーテーブルへの挿入です...後続の詳細テーブルや別のヘッダーテーブルへの挿入など...すべてロールバック...ただし、ロールバック後にテーブルを調べると、すべてのテーブルにレコードがありません、最初のものを除いて。
//Create receipt, ic, printq; update pod, poh
public List<ActionConfirmation<int>> CreateReceipt(
IEnumerable<ReceiptDetailPalletListViewModel> viewModelList,
int intUserId,
int intFacilityId,
int intLocationId
)
{
var dbContext = new InventoryMgmtContext();
//Opening connection
dbContext.Database.Connection.Open();
int intReceiptHdrId = 0;
int intICHdrId = 0;
var results = new List<ActionConfirmation<int>>();
foreach (ReceiptDetailPalletListViewModel viewModel in viewModelList)
{
if (viewModel.ReceivedQty > 0)
{
using (TransactionScope transaction = new TransactionScope())
{
//Create Receipt Header
ActionConfirmation<int> rcptHdrResult = CreateReceiptHeader(
dbContext,
intUserId,
intFacilityId); <===== This Tran never rolls back. Insert occured.
results.Add(rcptHdrResult);
if (!rcptHdrResult.WasSuccessful) //Recp Hdr create failed.
{
CloseFailedTrans(dbContext, transaction);
return results;
}
intReceiptHdrId = rcptHdrResult.Value;
//Create new ICHeader
ActionConfirmation<int> icHdrResult = CreateICHeader(
dbContext,
intUserId,
intFacilityId,
intLocationId,
intReceiptHdrId
);
results.Add(icHdrResult);
if (!icHdrResult.WasSuccessful)
{
CloseFailedTrans(dbContext, transaction);
return results;
}
intICHdrId = icHdrResult.Value;
//Create new ICDetail
ActionConfirmation<int> icDtlResult = CreateICDetail(
dbContext,
intICHdrId,
viewModel.ItemId,
viewModel.PODetailId,
viewModel.ReceivedQty,
intUserId
);
results.Add(icDtlResult);
if (!icDtlResult.WasSuccessful)
{
CloseFailedTrans(dbContext, transaction);
return results;
}
//Create new Recpt Detail
ActionConfirmation<int> rcptDtlResult = CreateReceiptDetail(
dbContext,
intReceiptHdrId,
viewModel.PODetailId,
viewModel.ReceivedQty,
intUserId
);
results.Add(rcptDtlResult);
if (!rcptDtlResult.WasSuccessful)
{
CloseFailedTrans(dbContext, transaction);
return results;
}
//Update PO Detail qty and Header status
List<ActionConfirmation<int>> poResults = UpdatePODetail(
dbContext,
viewModel.PODetailId,
viewModel.ReceivedQty,
intUserId
);
foreach (ActionConfirmation<int> poResult in poResults)
{
results.Add(poResult);
if (!poResult.WasSuccessful)
{
CloseFailedTrans(dbContext, transaction);
return results;
}
}
//Create new Print Q
ActionConfirmation<int> printqResult = CreatePrintQRecords(
dbContext,
intICHdrId,
intFacilityId,
intUserId
);
results.Add(printqResult);
if (!printqResult.WasSuccessful)
{
CloseFailedTrans(dbContext, transaction);
return results;
}
//Everything inserted correctly
CloseSuccessTrans(dbContext, transaction);
} //using statement
} //if rcv qty > 0
} // for each loop
dbContext.Database.Connection.Dispose();
return results;
}
トランザクション関連のメソッドは次のとおりです。
// Close DB Connections and transaction
private void CloseFailedTrans(InventoryMgmtContext dbContext, TransactionScope transaction)
{
//TODO: logging
CloseTrans(dbContext, transaction);
}
// Close DB Connections and transaction
private void CloseSuccessTrans(InventoryMgmtContext dbContext, TransactionScope transaction)
{
transaction.Complete();
CloseTrans(dbContext, transaction);
}
// Close DB Connections and transaction
private void CloseTrans(InventoryMgmtContext dbContext, TransactionScope transaction)
{
transaction.Dispose();
}
これは、挿入を行うメソッドの1つの例です。それらはすべて同じパターンに従います。
//Create Receipt Header
private ActionConfirmation<int> CreateReceiptHeader(
InventoryMgmtContext dbContext,
int intUserId,
int intFacilityId
)
{
//var repository = new Repository<ReceiptHeader>(dbContext);
var repository = new ReceiptHeaderRepository(dbContext);
//Create new Receipt Header
ReceiptHeader rcptHdr = new ReceiptHeader()
{
FacilityId = intFacilityId,
StatusId = 1,
CreatedById = intUserId,
CreatedOn = DateTime.Now,
ModifiedById = intUserId,
ModifiedOn = DateTime.Now
};
return repository.Insert(rcptHdr);
}
そして、これがリポジトリ挿入メソッドです:
public virtual ActionConfirmation<int> Insert(TRepository entity)
{
try
{
_dataContext.Entry(entity).State = System.Data.EntityState.Added;
_dataContext.SaveChanges();
return CRUDMessage(true, "saved", entity);
}
catch (Exception ex)
{
return CRUDMessage(false, "save", entity, ex);
}
}