【发布时间】:2021-11-02 16:04:01
【问题描述】:
在 netcore 5 C# 中,我在应用程序开始时检查数据库是否在最新版本上,如果不是,则根据特定客户安装的版本,它会自动更新(并针对每个客户执行特定操作)。
我正在重构并试图查看是否可以用 Dapper 调用替换当前的 sql 执行调用,但失败了:
一个。例如,我在字符串中有这段 sql:
SET NUMERIC_ROUNDABORT OFF
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT, QUOTED_IDENTIFIER, ANSI_NULLS, NOCOUNT ON SET DATEFORMAT YMD SET XACT_ABORT ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
DECLARE @items AS CURSOR
DECLARE @item AS nvarchar(250)
SET @items = CURSOR FOR
SELECT
N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(t.parent_object_id)) + N'.' + QUOTENAME(OBJECT_NAME(t.parent_object_id)) + ' DROP CONSTRAINT ' + QUOTENAME(t.name) + N';'
FROM
[sys].[check_constraints] AS t
WHERE
t.is_ms_shipped = 0
OPEN @items FETCH NEXT FROM @items INTO @item WHILE @@FETCH_STATUS = 0
BEGIN
EXEC (@item)
FETCH NEXT FROM @items INTO @item
END
CLOSE @items
DEALLOCATE @items
COMMIT TRANSACTION
b.我用 Dapper 运行这个(在事务中):
public IDbConnection DbConnection
{
get
{
return new SqlConnection(_connectionstring);
}
}
using IDbConnection db = DbConnection;
await db.ExecuteAsync(statement)
并且失败并显示“System.PlatformNotSupportedException:此平台不支持分布式事务。”
c。当我将 dapper 调用替换为:
string connectionString = _context.Database.GetDbConnection().ConnectionString;
SqlConnection _connection = new SqlConnection(connectionString);
await _connection.ExecuteCommandAsync(statement).ConfigureAwait(false);
它运行良好(以及之后的所有其他数百条 sql 语句)
围绕它的交易是:
using (TransactionScope scope
= new TransactionScope(TransactionScopeOption.Required, System.TimeSpan.FromMinutes(10),
TransactionScopeAsyncFlowOption.Enabled))
{
// a loop with hundreds of sql files and corresponding calls
// to execute
}
(我知道https://github.com/dotnet/runtime/issues/19318)
根据要求提供完整的堆栈跟踪
System.PlatformNotSupportedException: This platform does not support distributed transactions.
at System.Transactions.Distributed.DistributedTransactionManager.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken)
at System.Transactions.TransactionInterop.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken)
at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)
at System.Transactions.EnlistableStates.Promote(InternalTransaction tx)
at System.Transactions.Transaction.Promote()
at System.Transactions.TransactionInterop.ConvertToDistributedTransaction(Transaction transaction)
at System.Transactions.TransactionInterop.GetExportCookie(Transaction transaction, Byte[] whereabouts)
at System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transaction transaction, Byte[] whereAbouts)
at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()
--- End of stack trace from previous location ---
at Dapper.SqlMapper.ExecuteImplAsync(IDbConnection cnn, CommandDefinition command, Object param) in /_/Dapper/SqlMapper.Async.cs:line 645
【问题讨论】:
-
您不需要
CURSOR,只需使用STRING_AGG。 -
你不应该从属性获取器返回
new对象,尤其是像SqlConnection这样的昂贵对象 - 你会泄露本地资源大大地。属性 getter 应该没有副作用。 -
“并且失败并显示“System.PlatformNotSupportedException:此平台不支持分布式事务。” - 请发布该异常的堆栈跟踪。
-
.NET Core 不支持分布式事务(请参阅 stackoverflow.com/questions/56328832/… ) - 我认为您的 ADO 代码有效,因为事务在 SQL 代码中完成 - 尽管我承认我不确定(分布式事务是一个可以'o'蠕虫,imo)
-
显然工作的 ExecuteCommandAsync:它在哪里定义?这听起来不像普通的 ADO.NET,所以:它是从哪里来的?另请注意:Dapper also 只使用 ADO.NET,所以如果 Dapper 以这种方式失败,它来自 来自 ADO.NET;我很好奇这种其他方法在做什么,因此问题
标签: c# entity-framework dapper asp.net-core-5.0