我如何修复"多线程"并且"不允许新交易"使用Telerik Open Access时出错?

时间:2017-01-18 19:25:52

标签: asp.net-mvc entity-framework telerik telerik-open-access openaccess

我们有一个使用Telerik Open Access的asp.net MVC应用程序。一旦我们将数据投入生产,我们就会遇到各种各样的问题。 Telerik不再支持Open Access,因此我们无法从他们那里获得任何帮助,但我们现在应该上线,并且现在没有预算时间可以改变。有人可以就如何解决这些问题给我一些建议吗?

我们在更新和插入记录时遇到相同的错误,但这些问题并不总是会发生。我从来没有从我的计算机上的Visual Studio运行解决方案或将项目部署到我们的测试服务器后得到这些错误。在生产服务器上,当多个用户使用该应用程序时,我们开始看到错误。

示例代码就是这个插入函数:

public void CreateAttachments(tblCoDoc obj)
{
    try
    {
        dat.Add(obj);
        dat.SaveChanges();
    }
        catch (Exception exception)
        {
            throw exception;
        }
}

和此更新功能:

public void UpdateWorkOrderApprGen(tblWorkOrder obj)
    {
        var context = new KoorsenOpenAccessContext();
        var upd =
        (
            from workOrder in dat.tblWorkOrders
            where workOrder.WorkOrderId == obj.WorkOrderId
            select workOrder
        ).FirstOrDefault();

        if (upd != null)
        {
            upd.ReferenceNumber = obj.ReferenceNumber;
            upd.CustomerContract = obj.CustomerContract;
            upd.VendorContract = obj.VendorContract;
            upd.DateResolved = obj.DateResolved;

            try
            {
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

在这两种情况下,这些方法都在一个名为Repository的类中。为此类定义了一个私有变量(KOpenAccessContext是在实现OpenAccessContext类的项目中定义的类):

private static KOpenAccessContext dat = null;

然后在Repository构造函数中,将该私有变量分配给新的KOpenAccessContext:

dat = new KoorsenOpenAccessContext();

我们收到的错误消息是

  

Telerik.OpenAccess.Exceptions.DataStoreException:Telerik.OpenAccess.RT.sql.SQLException:不允许新事务,因为会话中还有其他线程在运行。

  

[InvalidOperationException:无法启动第二次交易]

第一个是最常见的。

这篇文章:SqlException from Entity Framework - New transaction is not allowed because there are other threads running in the session。表明问题来自for循环中的save,而事实并非如此。

第三个答案建议将代码放入使用事务并使用上下文块;我收到这个错误:

  

Telerik.OpenAccess.OpenAccessException:System.InvalidOperationException:此SqlTransaction已完成;它不再可用了。

我发现这篇文章:http://www.telerik.com/forums/how-do-i-fix-a-new-transaction-is-not-allowed-error-is-telerik-open-access#swcnW_tPGEWglUih1TEAKg建议我创建"使用短生存环境实例"。对我而言,这意味着要创建一个新的Open Access。我尝试了这个并且仍然得到了#34;不允许新的交易"错误:

public void CreateAttachments(tblCoDoc obj)
{

    try
    {
        var db = new KoorsenOpenAccessContext();
        db.Add(obj);
        db.SaveChanges();
    }
        catch (Exception exception)
        {
            throw exception;
        }
}

我真的很茫然,我有一位客户和老板在找我寻求解决方案。我很想知道原因(想想可能是因为有多个用户),但我真正需要的是一个解决方案。我怎样才能解决这个问题呢?

1 个答案:

答案 0 :(得分:0)

我认为你有几个问题正在发生。您提到您使用的存储库模式具有使用以下代码初始化的私有静态Context:

dat = new KoorsenOpenAccessContext();

如果你的创建和更新函数在存储库中,那么他们应该使用上下文的这个实例(dat)而不是创建自己的函数私有实例:

public void UpdateWorkOrderApprGen(tblWorkOrder obj)
    {
        // Don't do this, use the repository instance of the context instead
        // var context = new KoorsenOpenAccessContext();
        var upd =
        (
            from workOrder in dat.tblWorkOrders
            where workOrder.WorkOrderId == obj.WorkOrderId
            select workOrder
        ).FirstOrDefault();

        if (upd != null)
        {
            upd.ReferenceNumber = obj.ReferenceNumber;
            upd.CustomerContract = obj.CustomerContract;
            upd.VendorContract = obj.VendorContract;
            upd.DateResolved = obj.DateResolved;

            try
            {
                dat.SaveChanges();  // Use the repository's context here
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

确保您的存储库实现IDisposable,并通过调用dat.Dispose()正确处理存储库的上下文

您的另一个选择是跳过存储库模式并删除存储库私有上下文实例(dat)。请改用上下文的函数私有实例。 Telerik OpenAccess最佳实践建议使用using语句来确保上下文已关闭并正确处理:

public void CreateAttachments(tblCoDoc obj)
{    
    try
    {
        using (var db = new KoorsenOpenAccessContext())
        {
            db.Add(obj);
            db.SaveChanges();
        }
    }
    catch (Exception exception)
    {
        throw exception;
    }
}