阅读本文后,我决定仔细研究一下我使用Dapper的方式.
我在一个空数据库上运行此代码
var members = new List<Member>();
for (int i = 0; i < 50000; i++)
{
members.Add(new Member()
{
Username = i.toString(),
IsActive = true
});
}
using (var scope = new TransactionScope())
{
connection.Execute(@"
insert Member(Username, IsActive)
values(@Username, @IsActive)", members);
scope.Complete();
}
Run Code Online (Sandbox Code Playgroud)
花了大约20秒钟.这是2500插入/秒.不错,但考虑到博客达到45k插入/秒,也不是很好.在Dapper中有更有效的方法吗?
另外,作为旁注,通过Visual Studio调试器运行此代码需要3分钟!我认为调试器会慢一点,但我很惊讶地看到了这么多.
UPDATE
所以这
using (var scope = new TransactionScope())
{
connection.Execute(@"
insert Member(Username, IsActive)
values(@Username, @IsActive)", members);
scope.Complete();
}
Run Code Online (Sandbox Code Playgroud)
还有这个
connection.Execute(@"
insert Member(Username, IsActive)
values(@Username, @IsActive)", members);
Run Code Online (Sandbox Code Playgroud)
都花了20秒.
但这需要4秒!
SqlTransaction …Run Code Online (Sandbox Code Playgroud) 我刚开始玩Dapper.到目前为止,我喜欢它.小巧玲珑不适用TransactionScope吗?我注意到,即使我从不打电话,TransactionScope.Complete我的更改仍然会提交到数据库.如果现在不支持TransactionScope,是否有任何计划支持它?如果没有那么你必须使用传统的事务管理(System.Transactions.Transaction)?
更新:我刚刚通过Twitter与Sam谈过.它应该工作.我将在明天上午(工作中)更新它的详细信息,看看是否有人可以弄清楚为什么我的更改仍然被提交到数据库,即使我从未调用完成.
很简单的问题:是否可以System.Transactions.TransactionScope与SqlBulkCopy?一起使用?文档事务和批量复制操作没有提到任何内容(至少从.NET 4.0开始),我的测试表明它不会自动登记TransactionScope.
我已经阅读过(或者从同事那里听到)在.NET中,TransactionScope可以达到超时,然后是VoteCommit(而不是VoteRollback).这是准确还是传闻?我无法在网上找到谈论这个问题的信息(如果这是一个问题),所以我想知道是否有人有任何直接的经验,可以解决一些问题?
我正在寻找这个错误根源的描述:"另一个会话正在使用的事务上下文".
我有时会在我的一个单元测试中得到它,所以我不能提供repro代码.但我想知道什么是"按设计"错误的原因.
更新:错误从SQL Server 2008返回为SqlException.我收到错误的地方似乎是单线程的.但是我可能有单元测试交互,因为我得到了错误,一次运行几个测试(VS2008sp1中的MSTest).但失败的测试看起来像:
.
System.Data.SqlClient.SqlException: Transaction context in use by another session.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.PropagateTransactionCookie(Byte[] cookie)
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.GetConnection(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection …Run Code Online (Sandbox Code Playgroud) 我创建了一个sqlconnection,CN1.然后打开CN1.稍后在代码中有一个transactioncope.如果我在这个CN1连接上执行sql命令,这是在事务中吗?
代码看起来像这样;
SqlConnection cn1 = new SqlConnection();
cn1.Open(); //connection opened when there is no ambient transaction.
...
using(TransactionScope scope = new TransactionScope())
{
SqlCommand cmd; //a typical sql command.
...
cmd.ExecuteNonQuery(); //Is this command within transaction?
...
}
Run Code Online (Sandbox Code Playgroud) 我想知道TransactionScope类如何工作以保持不同方法调用之间的事务(不需要将其作为参数传递),我开始怀疑.我对这个问题有两点考虑:
通过Telerik JustDecompile查看TransactionScope的实现,我发现当前事务存储在System.Transactions.ContextData类的ThreadStatic成员中(下面的代码).
internal class ContextData
{
internal TransactionScope CurrentScope;
internal Transaction CurrentTransaction;
internal DefaultComContextState DefaultComContextState;
[ThreadStatic]
private static ContextData staticData;
internal WeakReference WeakDefaultComContext;
internal static ContextData CurrentData
{
get
{
ContextData contextDatum = ContextData.staticData;
if (contextDatum == null)
{
contextDatum = new ContextData();
ContextData.staticData = contextDatum;
}
return contextDatum;
}
}
public ContextData()
{
}
}
Run Code Online (Sandbox Code Playgroud)
CurrentData属性由TransactionScope的PushScope()方法调用,最后一个属性由大多数TransactionScope构造函数使用.
private void PushScope()
{
if (!this.interopModeSpecified)
{
this.interopOption = Transaction.InteropMode(this.savedCurrentScope);
}
this.SetCurrent(this.expectedCurrent);
this.threadContextData.CurrentScope = this;
}
public TransactionScope(TransactionScopeOption scopeOption)
{
// …Run Code Online (Sandbox Code Playgroud) 我想创建一个事务,在子事务中写入一些数据,读回数据,然后回滚事务.
using(var transaction = new TransactionScope())
{
using(var transaction = new TransactionScope())
{
// save data via LINQ / DataContext
transaction.Complete();
}
// Get back for assertions
var tempItem = // read data via LINQ / DataContext THROWS EXCEPTION
}
Run Code Online (Sandbox Code Playgroud)
但是在阅读时我得到"System.Transactions.TransactionException:该操作对于事务的状态无效."
我应该如何设置事务属性以避免这种情况?
我刚刚开始使用TransactionScope,我发现总会遇到意想不到的事情需要永远调试.
我认为拥有这些的综合列表对于那些"奇怪的错误"情况来说是很好的,并且还可以扩展我们对平台奇怪性的了解.
关于我将如何使用事务范围的一些上下文:
在什么情况下代码可以包含在System.Transactions.TransactionScope仍然提交中,即使抛出异常并且最外层范围从未调用过提交?
包含一个顶级方法using (var tx = new TransactionScope()),并调用也TransactionScope以相同方式使用的方法.
我正在使用带有关联tableadapters的类型化数据集.可能是因为某些原因,适配器中的命令没有出现?你们中的任何人都知道如何检查他们是否在环境TransactionScope中加入?
.net ×7
transactions ×4
c# ×3
dapper ×2
sql-server ×2
sqlbulkcopy ×2
asp.net ×1
msdtc ×1
performance ×1
threadstatic ×1