我们有一个使用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;
}
}
我真的很茫然,我有一位客户和老板在找我寻求解决方案。我很想知道原因(想想可能是因为有多个用户),但我真正需要的是一个解决方案。我怎样才能解决这个问题呢?
答案 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;
}
}