简体   繁体   中英

execute stored procedure inside Entity Framework transaction

I have a problem when I execute a stored procedure inside an opened transaction in Entity Framework.

The problem is that (look at the code) when I execute the stored procedure p_RecalcCost the return value is correct, but the value on the database will not change.

This let me think that the update operation done in the stored procedure is outside my transaction.

Any idea?

public bool myMethod(Entities ctx=null)
{
   bool ok = true;
   var context = ctx == null ? new Entities() : ctx;
   var dbTran = context.Database.CurrentTransaction ?? context.Database.BeginTransaction();
   List<MyObject> rows= MyObject.getRows(id, context);

   foreach (MyObject ier in rows)
   {
       MyObject oldObj = MyObject.GetEntity(ier.ID,context);
       decimal oldCost =  oldObj.Cost;


       System.Data.Entity.Core.Objects.ObjectParameter myOutputParamDecimal = new System.Data.Entity.Core.Objects.ObjectParameter("CostRes", typeof(decimal));
      context.p_RecalcProductCost(ier.ID, myOutputParamDecimal);

      context.SaveChanges();
      decimal newCost = Convert.ToDecimal(myOutputParamDecimal.Value); 


   }

  ....ok is always true
 if (ctx == null)
 {
    if (ok)
        dbTran.Commit();
    else
        dbTran.Rollback();

    context.Dispose();
  }

  return ok;
}

Here the code of the stored procedure

CREATE PROCEDURE [dbo].[p_RecalcProductCost]
@ID_Product int null,
@CostRes decimal(10,2) OUTPUT

AS
BEGIN

SET NOCOUNT ON;
SET FMTONLY OFF;

SELECT TOP 1 @CostRes=100 --is an example, this is a result of operations

--update cost on table Product
UPDATE Product set Cost = @CostRes
WHERE (@ID_Product IS NULL OR (@ID_Product is not null AND ID_Product = @ID_Product))

--update cost on another table
UPDATE ProductSupplier 
SET ps.Cost = CostRes   
WHERE
(@ID_Product IS NULL OR (@ID_Product is not null AND ps.ID_Product = @ID_Product)) 

END

If, in DEBUG, after the stored execution, I do a select on the DB with TRANSACTION ISOLATION LEVEL READ UNCOMMITTED the Cost is 100, but when The transaction ends the cost on the DB is NULL.

There are multiple issues concerning context lifetime/scope and transcation lifetime.

The issue is most probably because you don't commit the transaction , so it will be rolled back.

Statements like

var context = ctx == null ? new Entities() : ctx;

and

var dbTran = context.Database.CurrentTransaction ?? context.Database.BeginTransaction();

are an issue as it shows that you have no idea on who owns the connection/transaction, so you will have to provide code to manage this.

Try to use using statements, one way you could handle this:

public bool myMethod()
{
    if (ctx == null)
    {
        using (ctx = new Entities())
        {
            using (var dbTran = ctx.Database.BeginTransaction())
            {
                Update(ctx); // you need to return the values here
                dbTran.Commit();
            }
        }
    }
    else
    {
        if (ctx.Database.CurrentTransaction == null)
        {
            using (var dbTran = ctx.Database.BeginTransaction())
            {
                Update(ctx); // you need to return the values here
                dbTran.Commit();
            }
        }
        else
        {
            Update(ctx); // you need to return the values here
        }
    }
}

private void Update(DbContext context)
{
    List<MyObject> rows = MyObject.getRows(id, context);

    foreach (MyObject ier in rows)
    {
        MyObject oldObj = MyObject.GetEntity(ier.ID, context);
        List<p_Result> res = context.p_RecalcCost(ier.ID).ToList<p_Result>();
        decimal oldCost = oldObj.Cost;
        decimal newCost = (decimal) res[0].Cost;
    }
}

The problem was not the using because I'm Disposing the context at the end of the method.

 Product p= Product.GetEntity(ier.ID, context);
 context.Entry(updProduct).Reload();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM