gpt4 book ai didi

c# - Entity Framework 强制分布式事务

转载 作者:太空狗 更新时间:2023-10-29 21:44:25 25 4
gpt4 key购买 nike

我无法获得以下代码,该代码仅使用单个上下文接触单个数据库以在不升级到 MSDTC 的情况下运行,并且在 context.SaveChanges() 上抛出异常:

public void DeleteGroupDetails(int groupId)
{
// Note there is no ambient tx
var thisIsNull = Transaction.Current;

using (var scope = new TransactionScope())
{
var thisIsNotNull = Transaction.Current;

using (var context = new MyDbEntities())
{
var deleted = context.tblGroups.Where(x => x.GroupID == groupId);

context.tblGroups.RemoveRange(deleted);

try
{
context.SaveChanges();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}

//scope.Complete();
}
}

异常是“基础提供程序在打开时失败。--> 合作伙伴事务管理器已禁用其对远程/网络事务的支持。(HRESULT 异常:0x8004D025)”

注意:

  • 这是使用 EF 6 和 SQL Server 2005
  • 由于数据库服务器被锁定,我无法使用 MSDTC
  • 我想在 POC 中使用 TransactionScope,因为它将在内置了 TransactionScope 的 WCF 中运行,我不想在我的代码中乱扔事务管理。
  • 类似的项目使用NHibernate没有这个问题

连接字符串是:

connectionString="metadata=res:///ResourceAccess.MyDb.csdl|res:///ResourceAccess.MyDb.ssdl|res://*/ResourceAccess.MyDb.msl;provider =System.Data.SqlClient;provider connection string="data source=wil-gvpsqldev01;initial catalog=MyDb;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework""providerName="System.Data.EntityClient"/>

System.Transactions 诊断是:

<E2ETraceEvent>
<System>
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2014-10-31T14:39:43.0061489Z" />
<Source Name="System.Transactions" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="CCS.Host.Console.vshost" ProcessID="64568" ThreadID="13"/>
<Channel/>
<Computer>xxx</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord Severity="Information">
<TraceIdentifier>http://msdn.microsoft.com/2004/06/System/Transactions/TransactionCreate</TraceIdentifier>
<Description>Transaction Created</Description>
<AppDomain>CCS.Host.Console.vshost.exe</AppDomain>
<ExtendedData>
<TraceSource>[Lightweight]</TraceSource>
<TransactionTraceIdentifier>
<TransactionIdentifier>2e0814b3-7dd2-4c05-ad69-c3787d95c208:1</TransactionIdentifier>
<CloneIdentifier>1</CloneIdentifier>
</TransactionTraceIdentifier>
</ExtendedData>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent>
<System>
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2014-10-31T14:39:43.0181489Z" />
<Source Name="System.Transactions" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="CCS.Host.Console.vshost" ProcessID="64568" ThreadID="13"/>
<Channel/>
<Computer>xxx</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord Severity="Information">
<TraceIdentifier>http://msdn.microsoft.com/2004/06/System/Transactions/TransactionScopeCreated</TraceIdentifier>
<Description>TransactionScope Created</Description>
<AppDomain>CCS.Host.Console.vshost.exe</AppDomain>
<ExtendedData>
<TraceSource>[Base]</TraceSource>
<TransactionTraceIdentifier>
<TransactionIdentifier>2e0814b3-7dd2-4c05-ad69-c3787d95c208:1</TransactionIdentifier>
<CloneIdentifier>2</CloneIdentifier>
</TransactionTraceIdentifier>
<TransactionScopeResult>CreatedTransaction</TransactionScopeResult>
</ExtendedData>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent>
<System>
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2014-10-31T14:39:49.1921489Z"/>
<Source Name="System.Transactions"/>
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}"/>
<Execution ProcessName="CCS.Host.Console.vshost" ProcessID="64568" ThreadID="13"/>
<Channel/>
<Computer>ccc</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord Severity="Information">
<TraceIdentifier>http://msdn.microsoft.com/2004/06/System/Transactions/Enlistment</TraceIdentifier>
<Description>Enlistment Created</Description>
<AppDomain>CCS.Host.Console.vshost.exe</AppDomain>
<ExtendedData>
<TraceSource>[Lightweight]</TraceSource>
<EnlistmentTraceIdentifier>
<ResourceManagerId>00000000-0000-0000-0000-000000000000</ResourceManagerId>
<TransactionTraceIdentifier>
<TransactionIdentifier>2e0814b3-7dd2-4c05-ad69-c3787d95c208:1</TransactionIdentifier>
<CloneIdentifier>2</CloneIdentifier>
</TransactionTraceIdentifier>
<EnlistmentIdentifier>0</EnlistmentIdentifier>
</EnlistmentTraceIdentifier>
<EnlistmentType>PromotableSinglePhase</EnlistmentType>
<EnlistmentOptions>None</EnlistmentOptions>
</ExtendedData>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent >
<System >
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Error">0</SubType>
<Level>2</Level>
<TimeCreated SystemTime="2014-10-31T14:39:50.8941489Z" />
<Source Name="System.Transactions" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="CCS.Host.Console.vshost" ProcessID="64568" ThreadID="13" />
<Channel/>
<Computer>ccc</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord Severity="Error">
<TraceIdentifier>http://msdn.microsoft.com/2004/06/System/Transactions/TransactionException</TraceIdentifier>
<Description>TransactionException Thrown</Description>
<AppDomain>CCS.Host.Console.vshost.exe</AppDomain>
<ExtendedData xmlns="http://schemas.microsoft.com/2004/03/Transactions/TransactionExceptionTraceRecord">
<TraceSource>[Distributed]</TraceSource>
<ExceptionMessage>The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)</ExceptionMessage>
</ExtendedData>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent >
<System >
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Warning">0</SubType>
<Level>4</Level>
<TimeCreated SystemTime="2014-10-31T14:39:50.9591489Z" />
<Source Name="System.Transactions" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="CCS.Host.Console.vshost" ProcessID="64568" ThreadID="13" />
<Channel/>
<Computer>ccc</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Warning">
<TraceIdentifier>http://msdn.microsoft.com/2004/06/System/Transactions/EnlistmentCallbackNegative</TraceIdentifier>
<Description>Enlistment Callback Negative</Description>
<AppDomain>CCS.Host.Console.vshost.exe</AppDomain>
<ExtendedData >
<TraceSource>[Lightweight]</TraceSource>
<EnlistmentTraceIdentifier>
<ResourceManagerId>00000000-0000-0000-0000-000000000000</ResourceManagerId>
<TransactionTraceIdentifier>
<TransactionIdentifier>2e0814b3-7dd2-4c05-ad69-c3787d95c208:1</TransactionIdentifier>
<CloneIdentifier>2</CloneIdentifier>
</TransactionTraceIdentifier>
<EnlistmentIdentifier>0</EnlistmentIdentifier>
</EnlistmentTraceIdentifier><EnlistmentCallback>Aborted</EnlistmentCallback>
</ExtendedData>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent >
<System >
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Warning">0</SubType>
<Level>4</Level>
<TimeCreated SystemTime="2014-10-31T14:39:50.9601489Z" />
<Source Name="System.Transactions" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="CCS.Host.Console.vshost" ProcessID="64568" ThreadID="13" />
<Channel/>
<Computer>ccc</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord Severity="Warning">
<TraceIdentifier>http://msdn.microsoft.com/2004/06/System/Transactions/TransactionAborted</TraceIdentifier>
<Description>Transaction Aborted</Description>
<AppDomain>CCS.Host.Console.vshost.exe</AppDomain>
<ExtendedData >
<TraceSource>[Lightweight]</TraceSource>
<TransactionTraceIdentifier>
<TransactionIdentifier>2e0814b3-7dd2-4c05-ad69-c3787d95c208:1</TransactionIdentifier>
</TransactionTraceIdentifier>
</ExtendedData>
</TraceRecord>
</DataIt

最佳答案

问题在于 EF 关闭了获取 groupId 的实体然后删除实体之间的连接。这导致了升级。解决方法是控制连接的打开和关闭:

http://msdn.microsoft.com/en-us/data/dn456849.aspx

Behavior in EF6 and future versions

For EF6 and future versions we have taken the approach that if the calling code chooses to open the connection by calling context.Database.Connection.Open() then it has a good reason for doing so and the framework will assume that it wants control over opening and closing of the connection and will no longer close the connection automatically.

我能找到的关于此行为的唯一文档是此博客条目中的表格,该表格暗示如果存在多个连接,2008 年之前的 SQL Server 版本将升级:

https://petermeinl.wordpress.com/2011/03/13/avoiding-unwanted-escalation-to-distributed-transactions/

这是我着陆的地方:

using System;
using System.Data;

namespace Services.ResourceAccess
{
public class ResourceAccess : IDisposable
{
private readonly Lazy<MyDbEntities> _context;

public ResourceAccess()
{
_context = new Lazy<MyDbEntities>(() =>
{
var context = new MyDbEntities();

context.Database.Connection.Open();

return context;
});
}

public void DeleteGroupDetails(int groupId)
{
var deleted = _context.Value.tblGroupDetails.Where(x => x.GroupID == groupId);

_context.Value.tblGroupDetails.RemoveRange(deleted);

_context.Value.SaveChanges();
}

public void Dispose()
{
if (_context.IsValueCreated)
{
if (_context.Value.Database.Connection.State == ConnectionState.Open)
{
_context.Value.Database.Connection.Close();
}
}
}
}
}

关于c# - Entity Framework 强制分布式事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26680562/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com