我正在比较不同ORM库和ADO.NET的对象实现速度。测试包括查询1次,10次,100次和1000次结果11次(我将调用1次)并再次重复整次测试10次,因此每次查询测试有10次。
1000查询没有跟踪实体的结果很有意思,因为期望第一次执行查询非常慢,以下(2-11)更快但下面的设置(2-10)比ADO快.NET!
EF Core测试代码。 Keys是11维和1000列的2维数组。
public override async Task TestFindByPK(int[,] keys)
{
// force load all assemblies before real executing
using (var forceLoad = new AdventureWorks2012Context())
{
var ignore = await forceLoad.ErrorLog.ToListAsync();
}
for (var t = 0; t < 10; t++)
{
using (var context = new AdventureWorks2012Context())
{
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var stopWatch = new Stopwatch();
for (var r = 0; r < keys.GetLength(0); r++)
{
List<int> rows = GetRow(ref keys, r);
stopWatch.Restart();
var result = await context.SalesOrderHeader.Where(so => rows.Contains(so.SalesOrderId)).ToListAsync();
stopWatch.Stop();
await PrintTestFindByPKReport(stopWatch.ElapsedMilliseconds);
}
}
Log.WriteLine($"Finish {t + 1} run{Environment.NewLine}");
Thread.Sleep(TimeSpan.FromSeconds(2));
}
await Log.WriteLineAsync($"Complete on {DateTime.Now.ToShortTimeString()}{Environment.NewLine}");
}
我猜测必须缓存查询结果,以便使用相同键的以下测试集可以从缓存中检索结果,否则EF Core必须比ADO.NET慢。
所以,问题1,EF Core是否在指定没有跟踪结果时缓存查询结果?
如果ADO.NET测试代码效率不高,这是ADO.NET测试的代码。
public override async Task TestFindByPK(int[,] keys)
{
await PreloadAssemblies();
var sql = "SELECT * FROM Sales.SalesOrderHeader WHERE SalesOrderID IN " + CreateInSQLCommand(keys.GetLength(1));
SqlConnection conn = null;
var stopWatch = new Stopwatch();
for (var t = 0; t < 10; t++)
{
try
{
conn = new SqlConnection(ConnectionString);
conn.Open();
var sqlCmd = new SqlCommand(sql, conn);
for (var r = 0; r < keys.GetLength(0); r++)
{
var rows = GetRow(ref keys, r);
stopWatch.Restart();
sqlCmd.Parameters.Clear();
sqlCmd.Parameters.AddRange(CreateParamForInClause(rows));
var reader = await sqlCmd.ExecuteReaderAsync();
SalesOrderHeaderSQLserver salesOrderHeader = null;
while (await reader.ReadAsync())
{
salesOrderHeader = new SalesOrderHeaderSQLserver();
salesOrderHeader.SalesOrderId = reader.GetInt32(0);
salesOrderHeader.RevisionNumber = reader.GetByte(1);
salesOrderHeader.OrderDate = reader.GetDateTime(2);
salesOrderHeader.DueDate = reader.GetDateTime(3);
salesOrderHeader.ShipDate = await ConvertTo<DateTime?>(reader, 4);
salesOrderHeader.Status = reader.GetByte(5);
salesOrderHeader.OnlineOrderFlag = reader.GetBoolean(6);
salesOrderHeader.SalesOrderNumber = reader.GetString(7);
salesOrderHeader.PurchaseOrderNumber = await ConvertTo<string>(reader, 8);
salesOrderHeader.AccountNumber = await ConvertTo<string>(reader, 9);
salesOrderHeader.CustomerID = reader.GetInt32(10);
salesOrderHeader.SalesPersonID = await ConvertTo<int?>(reader, 11);
salesOrderHeader.TerritoryID = await ConvertTo<int?>(reader, 12);
salesOrderHeader.BillToAddressID = reader.GetInt32(13);
salesOrderHeader.ShipToAddressID = reader.GetInt32(14);
salesOrderHeader.ShipMethodID = reader.GetInt32(15);
salesOrderHeader.CreditCardID = await ConvertTo<int?>(reader, 16);
salesOrderHeader.CreditCardApprovalCode = await ConvertTo<string>(reader, 17);
salesOrderHeader.CurrencyRateID = await ConvertTo<int?>(reader, 18);
salesOrderHeader.SubTotal = reader.GetDecimal(19);
salesOrderHeader.TaxAmt = reader.GetDecimal(20);
salesOrderHeader.Freight = reader.GetDecimal(21);
salesOrderHeader.TotalDue = reader.GetDecimal(22);
salesOrderHeader.Comment = await ConvertTo<string>(reader, 23);
salesOrderHeader.Rowguid = reader.GetGuid(24);
salesOrderHeader.ModifiedDate = reader.GetDateTime(25);
}
stopWatch.Stop();
reader.Close();
await PrintTestFindByPKReport(stopWatch.ElapsedMilliseconds);
}
}
catch (SqlException ex)
{
Console.WriteLine($"Exception message : {ex.Message}");
}
finally
{
conn.Dispose();
}
Log.WriteLine($"Finish {t + 1} run{Environment.NewLine}");
Thread.Sleep(TimeSpan.FromSeconds(2));
}
await Log.WriteLineAsync($"Complete on {DateTime.Now.ToShortTimeString()}" + Environment.NewLine);
}
其他奇怪的是第一个集总是慢于下面的集,我知道查询执行的时候它必须被处理并转换为相应的SQL命令,但它是缓存,但为什么2-11慢于以下测试集(它比第一次快得多)。
是否因为如果一组值不同,带有一组值的IN子句被视为不同?