Linq to Sql Udf 调用比普通调用更快 Ado.net
Linq to Sql Udf call faster than plain Ado.net
我们有一个遗留应用程序,我们在其中调用数据库中的用户定义函数。这个 Udf returns 一个非常大的 xml 字符串(大约 1971540 个字符)。令人惊讶的是,linq to sql 的 ExecuteMethodCall 运行得非常快,而普通的 Ado.Net DbDataReader.GetString() 很慢!!!
我们已经对调用进行了基准测试,L2S 可以在 4 秒内获取它,而普通 Ado.net DbDataReader.GetString() 可以在大约 37 秒内获取它。
查看 L2S 代码,它似乎使用相同的 DbDataReader.GetString() 方法,尽管是通过动态生成的 IL 代码。 http://referencesource.microsoft.com/#System.Data.Linq/SqlClient/Reader/ObjectReaderCompiler.cs,b2f6633a6c502138
我想了解是什么让 L2S 能够在如此短的时间内读取如此庞大的数据?
请注意,即使在第一次调用时它也运行得足够快,所以它可能不是缓存魔法。
编辑
using (DbConnection con = _dataContext.Database.Connection)
{
DbCommand cmd = con.CreateCommand();
cmd.CommandText = sql;
cmd.Transaction = _dataContext.Database.CurrentTransaction.UnderlyingTransaction;
parameters.Cast<System.Data.SqlClient.SqlParameter>().ToList().ForEach(x => cmd.Parameters.Add(x));
cmd.CommandTimeout = 500;
if (con.State != System.Data.ConnectionState.Open)
con.Open();
using (var reader = cmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess | System.Data.CommandBehavior.SingleResult | System.Data.CommandBehavior.SingleRow))
{
if (reader.Read())
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
var data = reader.GetString(0);
sw.Stop();
var et = sw.Elapsed.TotalSeconds;
}
}
}
此致。
最终经过大量的思考和调整...原来是 MARS 配置的问题!!
MARS 在我们最新的重构代码中打开(我认为是 EF 的默认行为),因为它在 Linq to sql 连接字符串中不存在。
一旦我们从连接字符串中删除 "MultipleActiveRecordSets=True;",它就可以正常工作。不确定为什么删除 MARS 会起作用。
希望对以后遇到类似问题的人有所帮助。
我们有一个遗留应用程序,我们在其中调用数据库中的用户定义函数。这个 Udf returns 一个非常大的 xml 字符串(大约 1971540 个字符)。令人惊讶的是,linq to sql 的 ExecuteMethodCall 运行得非常快,而普通的 Ado.Net DbDataReader.GetString() 很慢!!!
我们已经对调用进行了基准测试,L2S 可以在 4 秒内获取它,而普通 Ado.net DbDataReader.GetString() 可以在大约 37 秒内获取它。
查看 L2S 代码,它似乎使用相同的 DbDataReader.GetString() 方法,尽管是通过动态生成的 IL 代码。 http://referencesource.microsoft.com/#System.Data.Linq/SqlClient/Reader/ObjectReaderCompiler.cs,b2f6633a6c502138
我想了解是什么让 L2S 能够在如此短的时间内读取如此庞大的数据?
请注意,即使在第一次调用时它也运行得足够快,所以它可能不是缓存魔法。
编辑
using (DbConnection con = _dataContext.Database.Connection)
{
DbCommand cmd = con.CreateCommand();
cmd.CommandText = sql;
cmd.Transaction = _dataContext.Database.CurrentTransaction.UnderlyingTransaction;
parameters.Cast<System.Data.SqlClient.SqlParameter>().ToList().ForEach(x => cmd.Parameters.Add(x));
cmd.CommandTimeout = 500;
if (con.State != System.Data.ConnectionState.Open)
con.Open();
using (var reader = cmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess | System.Data.CommandBehavior.SingleResult | System.Data.CommandBehavior.SingleRow))
{
if (reader.Read())
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
var data = reader.GetString(0);
sw.Stop();
var et = sw.Elapsed.TotalSeconds;
}
}
}
此致。
最终经过大量的思考和调整...原来是 MARS 配置的问题!!
MARS 在我们最新的重构代码中打开(我认为是 EF 的默认行为),因为它在 Linq to sql 连接字符串中不存在。
一旦我们从连接字符串中删除 "MultipleActiveRecordSets=True;",它就可以正常工作。不确定为什么删除 MARS 会起作用。
希望对以后遇到类似问题的人有所帮助。