在事务中调用 WCF 方法会导致错误

问题描述 投票:0回答:1

我有一个复杂的应用程序并遇到了错误。我用以下代码简化了我的实际问题。

我有一个 WCF 服务,其方法可以在我的一个表上执行选择:

public string FindDocumentNumber(int documentId)
{
    using(var context = new MyDbContext())
    {
       return context.Documents.Where(x=>x.Id == documentId && x.Tag == "*")
                               .Select(x=>x.Number).FirstOrDefault();
    }   
}

在我的控制台应用程序中,我有以下代码:

using(var scope = new TransactionScope())
{
    using(var context = new MyDbContext())   
    {
        var doc = context.Documents.Where(x=>x.Id == 12345).FirstOrDefault();
        doc.Tag = "*";
        context.SaveChange();
    }

    ... 
    var number = myWCFService.FindDocumentNumber(12345); // At this point, I encounter an error
    ...
    //some other updates on document with Id = 12345 
    scope.Complete();
}

但是,运行代码时,遇到以下错误:

System.Data.Entity.Core.EntityCommandExecutionException
HResult=0x8013193C Message=执行时发生错误 命令定义。有关详细信息,请参阅内部异常。
来源= StackTrace:

内部异常1:SqlException:执行超时已过期。这 操作完成之前超时时间已过或 服务器没有响应。

内部异常2:Win32Exception:等待操作超时

问题出在哪里?

c# entity-framework wcf entity-framework-6 transactionscope
1个回答
0
投票

问题在于您尝试在事务范围内处置 DbContext。 Tx 范围将希望确保对 DbContext 的更改以及识别它的任何其他内容都会同时提交,这将阻塞

DbContext
Dispose
在其
using
块的末尾,这是最重要的。可能是您异常的根源。

如果 API 调用设置为在 Tx 范围内工作(我怀疑不是),那么您需要反转

using
块以避免该错误:

using(var context = new MyDbContext())   
{
    using(var scope = new TransactionScope())
    {
        var doc = context.Documents.Where(x=>x.Id == 12345).Single();
        doc.Tag = "*";
        context.SaveChange();

        ... 
        var number = myWCFService.FindDocumentNumber(12345); // At this point, I encounter an error
        ...
        //some other updates on document with Id = 12345 
        scope.Complete();
    }
}

然而,正如评论所说,Tx Scope 可能甚至没有必要。 DbContext 包装了自己的事务,因此如果存在您不想将更改提交到数据库的情况,只需避免调用“SaveChanges”,直到您满意所有内容都应该提交为止。

using(var context = new MyDbContext())   
{
    var doc = context.Documents.Where(x=>x.Id == 12345).Single();
    doc.Tag = "*";

    ... 
    var number = myWCFService.FindDocumentNumber(12345); // At this point, I encounter an error
        ...
    //some other updates on document with Id = 12345 

    if (everythingIsOk) // Use a flag, check state, whatever....
        context.SaveChanges();
}

事务范围旨在协调多个单独的操作,以确保它们全部一起提交或回滚。我看到使用单独事务的一个常见场景是,开发人员觉得他们需要先保存记录,例如获取生成的 ID,以便他们可以在其他地方使用或设置该 ID,但仍然希望选择“退出”该插入物。在极少数情况下,这是一个合法的问题,但更多时候这只是有限的实现,需要考虑更好的选择。

© www.soinside.com 2019 - 2024. All rights reserved.