Наткнулся на относительно часто используемый фрагмент кода, который поначалу казался неэффективным.(Я знаю, что оптимизация иногда бывает злой, но мне было интересно)
вводная часть - довольно простое выполнение SP + чтение возвращаемых данных:
try
{
await connection.OpenAsync();
using (var command = connection.CreateCommand())
{
command.CommandText = sql.ToString();
command.Parameters.AddRange(sqlParameters.ToArray());
var reader = await command.ExecuteReaderAsync();
if (reader.HasRows)
{
while (await reader.ReadAsync())
{
var item = await GetProjectElement(reader);
list.Add(item);
}
}
reader.Dispose();
}
}
finally
{
connection.Close();
}
Меня беспокоит функция
await GetProjectElement (reader)
private async Task<Project> GetProjectElement(DbDataReader reader)
{
var item = new Project
{
Id = await reader.GetFieldValueAsync<int>(1),
ParentId = await reader.IsDBNullAsync(2) ? default(int?) : await reader.GetFieldValueAsync<int>(2),
Name = await reader.IsDBNullAsync(3) ? default(string) : await reader.GetFieldValueAsync<string>(3),
Description = await reader.IsDBNullAsync(4) ? default(string) : await reader.GetFieldValueAsync<string>(4),
Address = await reader.IsDBNullAsync(5) ? default(string) : await reader.GetFieldValueAsync<string>(5),
City = await reader.IsDBNullAsync(6) ? default(string) : await reader.GetFieldValueAsync<string>(6),
PostalCode = await reader.IsDBNullAsync(7) ? default(string) : await reader.GetFieldValueAsync<string>(7),
Type = (ProjectTypeEnum)(await reader.GetFieldValueAsync<byte>(8)),
StartDate = await reader.IsDBNullAsync(9) ? default(DateTime?) : await reader.GetFieldValueAsync<DateTime>(9),
EstimatedEndDate = await reader.IsDBNullAsync(10) ? default(DateTime?) : await reader.GetFieldValueAsync<DateTime>(10),
ActualEndDate = await reader.IsDBNullAsync(11) ? default(DateTime?) : await reader.GetFieldValueAsync<DateTime>(11),
WebsiteUrl = await reader.IsDBNullAsync(12) ? default(string) : await reader.GetFieldValueAsync<string>(12),
Email = await reader.IsDBNullAsync(13) ? default(string) : await reader.GetFieldValueAsync<string>(13),
PhoneNumber = await reader.IsDBNullAsync(14) ? default(string) : await reader.GetFieldValueAsync<string>(14),
MobilePhoneNumber = await reader.IsDBNullAsync(15) ? default(string) : await reader.GetFieldValueAsync<string>(15),
Key = await reader.IsDBNullAsync(16) ? default(Guid?) : await reader.GetFieldValueAsync<Guid>(16),
OrganizationElementId = await reader.GetFieldValueAsync<int>(17),
CompanyOrganizationElementId = await reader.IsDBNullAsync(18) ? default(int?) : await reader.GetFieldValueAsync<int>(18),
IsArchived = await reader.GetFieldValueAsync<bool>(20),
IsDeleted = await reader.GetFieldValueAsync<bool>(21),
CreatedOn = await reader.GetFieldValueAsync<DateTime>(22),
CreatedBy = await reader.GetFieldValueAsync<string>(23),
ModifiedOn = await reader.IsDBNullAsync(24) ? default(DateTime?) : await reader.GetFieldValueAsync<DateTime>(24),
ModifiedBy = await reader.IsDBNullAsync(25) ? default(string) : await reader.GetFieldValueAsync<string>(25)
};
return item;
}
как вы можете видеть, существует МНОЖЕСТВО вызовов await, которые компилятор превращает в конечные автоматы, не так ли?
Здесь вы можете найти упрощенную версию того, как сгенерированный компилятором код здесь .Множество GOTO, что означает переключение контекста снова и снова.
Поскольку SP был выполнен без указания CommandBehavior - данные будут в непоследовательном режиме.(вероятно, причина в том, что строка таблицы не должна быть очень большой в байтах для этого случая Project
link )
Мои вопросы :
1) это злоупотребление асинхронностью / ожиданием без очевидной причины, потому что данные строки уже буферизированы в памяти, верно?
2) - это Task<Project>
чистые издержкив этом сценарии?
3) будет ли этот подход на самом деле иметь худшую производительность по сравнению с одним без await
ing
Заключительные мысли : Если я получу вещиправильно, мы хотели бы использовать CommandBehavior.SequentialAccess для больших строк таблицы, где содержимое может превышать разумную длину, что заставляет нас хотеть читать его асинхронно?(например, хранение varbinary (max) или BLOB-объектов)