Reputation: 4572
I am trying to wrap a series of database updates in a transaction scope. I was having issues where the first db update worked, but the second would fail. I think it has to do with the pay I was passing the DbContext to the methods by value...which in essence is creating a copy of it in the called method (right?). As such I think this was causing issues with the context not remaining in tact for the transaction...this is a little above my current understanding level and trying to learn, but this is my presumption at this point.
As such, I thought I'd need to pass the DbContext to the called method by Reference, but then get a warning about incorrect assignment of local variable.
So how do I use this encapsulation by having sub methods being called from within the using block and maintain the DbContext integrity?
Here's my wrapper method:
// define our transaction scope
var scope = new TransactionScope(
// a new transaction will always be created
TransactionScopeOption.RequiresNew,
// we will allow volatile data to be read during transaction
new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadUncommitted
}
);
try
{
// use the scope we just defined
using (scope)
{
// create a new db context
var ctx = new InventoryMgmtContext();
using (ctx)
{
//Initial count of rows in Alloc Needs
System.Diagnostics.Debug.WriteLine("Begin Alloc Need Recs: " + ctx.AllocationNeeds.Count().ToString());
//De-Allocate inventory container dtls
var deAllocInvenResult = DeAllocInvenForNeed(ref ctx, intFacilityId, needSourceType, intNeedSourceId, intUserId);
//Delete Allocation Need and Allocated Ctnr records
var deleteAllocNeedResult = DeleteAllocRecords(
ref ctx,
intFacilityId,
needSourceType,
intNeedSourceId
);
//var repository = new Repository<AllocationNeed>(ctx);
}
// everything good; complete
scope.Complete();
}
And here is one of the sub methods doing the updates:
//Delete Allocation Need and AllocatedContainers for alloc need id
private ActionConfirmation<int> DeleteAllocRecords(
ref InventoryMgmtContext ctx,
int intFacilityId,
AllocationNeed.NeedSourceTypeOptions needSourceType,
int intNeedSourceId
)
{
var repository = new Repository<AllocationNeed>(ctx);
//Delete Allocation Need and hence children in Allocated Containers
var srcType = needSourceType.ToString();
AllocationNeed allocNeed = repository.SearchFor(
x => x.FacilityId == intFacilityId
&& x.NeedSourceType == srcType
&& x.NeedSourceId == intNeedSourceId
).First();
//return repository.Delete(allocNeed, true);
ctx.Entry(allocNeed).State = System.Data.EntityState.Deleted;
ctx.SaveChanges();
//Deallocation was successful
return ActionConfirmation<int>.CreateSuccessConfirmation(
string.Format(
"Successfully deleted Need Id: {0} {1}",
needSourceType.ToString(),
intNeedSourceId
),
intNeedSourceId
);
}
Upvotes: 4
Views: 2622