【问题标题】:Unable to begin a distributed transaction using Entiy Framework无法使用实体框架开始分布式事务
【发布时间】:2018-01-27 03:46:47
【问题描述】:

我在执行这段代码时遇到以下错误:

private bool _updateList(SysInfo _sysInfo, List<pList> _pList)
{
    try
    {

        foreach (var p in _pList)
        {
            _context.spUpdatePListApprovalFlow(p.countryID, _sysInfo.User.JobRoleID, p.src, p.id, p.status, _sysInfo.User.Username);
        }

        return true;
    }
    catch (Exception ex) //debug only
    {
        throw; //throws error to the main try catch
    }
}

错误

无法执行操作,因为 OLE DB 提供程序“MSDASQL” 对于链接服务器“AS400_LINKEDSRV”,无法开始分布式 交易。

但是,当我在 SQL Management Studio 中运行存储过程时,一切正常:

exec [dbo].[spUpdatePListApprovalFlow]
        @CountryID  = 123456,
        @UserTypeID = 23456,
        @Src = 1,
        @Id = '123456789',
        @Status = 30,
        @Username  = 'username'

我已经厌倦了寻找答案没有任何效果......我尝试过的几件事:

  • 设置事务隔离级别读取未提交
  • 在存储过程中插入多个事务

这个 sp 上有 2 个子存储过程。一个写入应用程序数据库的表,另一个更新 as400 中的表。

【问题讨论】:

    标签: c# sql-server entity-framework stored-procedures ibm-midrange


    【解决方案1】:

    默认情况下,在 EF6 中,存储过程在显式事务中调用。您可以通过在创建特定 DbContext 实例后更改其配置来关闭它,或者通过在构造函数中更改它来为 DbContext 类型的所有实例关闭它。 EG

        using (var db = new Db())
        {
            db.Configuration.EnsureTransactionsForFunctionsAndCommands = false;
            //. . .
        }
    

    见:https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbcontextconfiguration.ensuretransactionsforfunctionsandcommands

    【讨论】:

    • 拜托,你能把文档的链接说 EF6 在显式事务中调用存储过程吗?
    【解决方案2】:

    好的,经过半天的尝试,我终于解决了。

    分辨率

    从 Entity Framework 6 降级到 Entity Framework 5 和 分布式事务错误已经消失。

    只需注意,如果您要这样做,您必须更改代码中的一些用法。 (在数据模型中的自动生成代码中也是如此)

    EF 6使用

    using System.Data.Entity.Core.Objects
    

    EF 5使用

    using System.Data.Objects;
    

    【讨论】:

    • 现在您已经确认不同版本的 EF 行为不同,您可以提出另一个关于 EF 的非常好的问题并找到问题的根源。
    【解决方案3】:

    如果您不需要分布式事务,您可以尝试在链接服务器的设置中禁用它们:

    EXEC master.dbo.sp_serveroption 
        @server=N'AS400_LINKEDSRV', 
        @optname=N'remote proc transaction promotion', 
        @optvalue=N'false'
    

    【讨论】:

    • 我不是 DBA,我只在我的 DB 中拥有管理员权限。然而这能解决问题吗?你能解释一下关闭这个有什么影响吗?如果需要,我可以要求他们这样做。
    • 这是更改 SQL Server 实例中链接服务器 AS400_LINKEDSRV 的设置。它没有接触远程 AS400 服务器。
    • 如果启用了分布式事务,如果一切都已配置并正常工作,那么事务跨越两个服务器,就好像它是一个服务器一样。如果事务不是分布式的,那么您的 SQL Server 只负责将本地更改包装到事务中,而远程服务器负责自己的更改。一个服务器上的更改可能会被持久化,而另一台服务器上的更改则不会。这在您的情况下是否可以接受取决于您的存储过程做什么。
    • 出现了另一个问题,我在另一个项目中的同事正在做我正在做的事情,但他使用的是旧版本的实体框架(4.0),我使用的是版本 6 你认为连接器的版本可能有问题?
    • 抱歉,@BrunoRodrigues,我从未使用过实体框架。当然,由于查询在 SSMS 中运行良好,问题在于您的 C# 代码和/或实体框架选项。也许 EF 启动了一些额外的事务,其中不仅包含此 SP,还包含其他内容,这导致事务被提升为分布式。也许 EF 默认情况下会以分布式方式启动所有事务,并且只有在实际使用两个不同的服务器时才会看到问题。您可以尝试深入研究 EF 设置,但我对 EF 无能为力。也许其他人会添加特定于 EF 的答案。
    【解决方案4】:

    请参阅此Microsoft page on Linked Servers

    您的系统管理员和/或 DBA 可能需要进行更改以解决您的 AS/400 服务器缺少的链接服务器定义。

    另一个可能的问题是 AS/400 服务器(来自 IBM)缺乏对 OLE DB 数据源的软件支持。这也是系统管理人员可能需要解决的问题。

    【讨论】:

      猜你喜欢
      • 2014-12-28
      • 2011-11-20
      • 2010-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-10
      相关资源
      最近更新 更多