[英]execute stored procedure inside Entity Framework transaction
在實體框架中打開的事務中執行存儲過程時遇到問題。
問題是(查看代碼)當我執行存儲過程 p_RecalcCost 時,返回值是正確的,但數據庫上的值不會改變。
這讓我覺得在存儲過程中完成的更新操作在我的事務之外。
任何想法?
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;
}
這里是存儲過程的代碼
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
如果在 DEBUG 中,在存儲執行之后,我在數據庫上執行 select 且未提交事務隔離級別讀取,則成本為 100,但當事務結束時,數據庫上的成本為 NULL。
關於上下文生命周期/范圍和事務生命周期存在多個問題。
這個問題很可能是因為你沒有commit
transaction
,所以它會被回滾。
像這樣的陳述
var context = ctx == null ? new Entities() : ctx;
和
var dbTran = context.Database.CurrentTransaction ?? context.Database.BeginTransaction();
是一個問題,因為它表明您不知道誰擁有連接/事務,因此您必須提供代碼來管理它。
嘗試使用 using 語句,這是您可以處理的一種方法:
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;
}
}
問題不在於使用,因為我在方法結束時處理上下文。
Product p= Product.GetEntity(ier.ID, context);
context.Entry(updProduct).Reload();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.