crichavin
crichavin

Reputation: 4572

Passing DbContext by Reference in Using block in Entity Framework

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

Answers (1)

crichavin
crichavin

Reputation: 4572

My assumption in that I had to pass one version of the context was incorrect. I found a good article here that explains how to wrap a transaction around multiple contexts.

Upvotes: 2

Related Questions