EF Bulk Extensions для меня работает очень медленно, но почему?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 EF Bulk Extensions для меня работает очень медленно, но почему?

Сообщение Anonymous »

У меня есть консольное приложение C# на .NET 6.0, использующее EF Core 6.0.35.
Я делаю вызов API, чтобы получить данные (из Geotab), которые я фильтрую, преобразую и вставить в мою БД. Каждая вставка содержит от 1000 до 2000 записей.
Моя таблица в SQL Server 2022 (v16.0.1135.2) выглядит следующим образом:

Код: Выделить всё

CREATE TABLE [dbo].[DiagnosticData]
(
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[DeviceId] [int] NOT NULL,
[DiagnosticId] [int] NOT NULL,
[Value] [float] NOT NULL,
[DateTime] [datetime2](7) NOT NULL,
[UpdateDateTime] [datetime2](7) NOT NULL
)
Соответствующий класс модели:

Код: Выделить всё

public class DiagnosticData
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Int64? Id { get; set; }
[Column("DeviceId")]
public int DeviceId { get; set; }
[Column("DiagnosticId")]
public int DiagnosticId { get; set; }
[Required]
public Double Value { get; set; }
[Required]
public DateTime DateTime { get; set; }
[Required]
public DateTime UpdateDateTime {  get; set; } = DateTime.UtcNow;
}
Я попробовал следующие три метода вставки данных:
ОДИН: Базовый код EF Core:

Код: Выделить всё

public static async Task BulkInsertAsyncEF(IEnumerable entities)
{
await using (PCContext _context = new PCContext())
{
_context.AddRangeAsync(entities);
await _context.SaveChangesAsync();
}
}
ДВА: (это не мой любимый метод, а скорее эксперимент по проверке времени выполнения)

Код: Выделить всё

public static async Task BulkInsertSqlAsync(IEnumerable diagnosticData)
{
await using (PCContext _context = new PCContext())
{
StringBuilder sb = new StringBuilder();

foreach (DiagnosticData dd in diagnosticData)
{
sb.Append("INSERT INTO DiagnosticData (DeviceId, DiagnosticId, Value, DateTime, UpdateDateTime) values (");
sb.Append(dd.DeviceId);
sb.Append(',');
sb.Append(dd.DiagnosticId);
sb.Append(',');
sb.Append(dd.Value);
sb.Append(",'");
sb.Append(dd.DateTime.ToString());
sb.AppendLine("',getdate());");
}
await _context.Database.ExecuteSqlRawAsync(sb.ToString());
}
}
ТРИ: Массовые расширения Entity Framework

Код: Выделить всё

public static async Task BulkInsertAsync(IEnumerable entities)
{
await using (PCContext _context = new PCContext())
{
using var transaction = _context.Database.BeginTransaction();
await _context.BulkInsertAsync(entities, options => { options.IncludeGraph = false; options.PreserveInsertOrder = false; });
transaction.Commit();
}
}
Они выполняются следующим образом:

Код: Выделить всё

IEnumerable
 diagnosticData = new List();
diagnosticData = statusData.Select(sd => new PC.DiagnosticData()
{
DateTime = sd.DateTime.Value,
DeviceId = devices.First(dv => dv.DeviceId == sd.Device.Id.ToString()).Id,
DiagnosticId = diagnostics.FirstOrDefault(di => di.DiagnosticId == sd.Diagnostic.ToString()).Id,
Value = sd.Data.Value
}
);

// await PC.DiagnosticData.BulkInsertSqlAsync(diagnosticData);
await PC.DiagnosticData.BulkInsertAsync(diagnosticData);
// await PC.DiagnosticData.BulkInsertAsyncEF(diagnosticData);

Код: Выделить всё

statusData
содержит ответ от API Geotab.
  • Метод первый требует от 10 до 15 секунд для вставки ~ 1000 записей, что, по моему мнению, слишком медленно. инстинкт (и эта страница).
  • Второй метод был быстрее на ~2 секунды для ~1000 записей (все равно слишком медленно!)
  • Третий метод было примерно таким же, как и первый метод.
Ни одна из записей НИКОГДА не будет существовать в БД, поэтому обновление никогда не потребуется.
Я пробовал на двух отдельных экземпляров SQL Server и получил те же результаты (один из них — моя локальная машина разработки без другого трафика)
Учитывая, что первый и третий методы занимают примерно одинаковое количество времени, можно предположить, что это проблема. на уровне EF, но что?

Подробнее здесь: https://stackoverflow.com/questions/792 ... me-but-why
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»