DBContext и Repository Pattern работают медленно - PullRequest
0 голосов
/ 08 января 2019

В моем решении есть два проекта: базовая библиотека классов .net с именем «Инфраструктура» и базовое веб-приложение .net с именем «Admin». В разделе «Инфраструктура» я реализовал шаблон репозитория для приложения DBContext, например:

public partial class ApplicationDbContext : DbContext
{
   ....
}

Интерфейсы:

public interface IGenericRepository<T> where T : class
{
    T Add(T t);
    ....
}

public interface ICustomersRepository : IGenericRepository<Customers>
{
    Customers GetCustomerByCompanyCode(string companyCode);
    void InsertOrUpdate(Customers toSync);
}

Generic:

public class GenericRepository<T> : IGenericRepository<T>, where T : class
{
    protected ApplicationDbContext _context;

    public GenericRepository(ApplicationDbContext context)
    {
        _context = context;
    }

    public virtual T Add(T t)
    {
        _context.Set<T>().Add(t);
        _context.SaveChanges();
        return t;
    }

    ....
}

Конкретная:

public class CustomersRepository : GenericRepository<Customers>, ICustomersRepository
{
    public CustomersRepository(ApplicationDbContext context) : base(context)
    {
    }
    ....
}

В веб-приложении: - Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options => options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"))); 
    ....
    services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
    services.AddScoped<ICustomersRepository, CustomersRepository>();
    ....
}

- CustomersController.cs

private readonly ICustomersRepository rep;

public CustomersController(ICustomersRepository rep, ....)
{
    this.rep = rep;
    ....    
}

public async Task DoImport()
{
    ....
    rep.InsertOrUpdate(mapper.Map<Customers>(item.Result));
    ....
}

Работает, но очень медленно: 300.000 вставок за несколько часов. Если я не использую шаблон репозитория, но попробуйте вставить вызывающий ApplicationDBContext напрямую, например:

using (var _context = new ApplicationDbContext())
{
     _context.Add(toSync);
     _context.SaveChanges();
}

время работы: 300.000 вставок за 6 минут.

Почему это происходит? Является ли шаблон репозитория лучшим выбором для разделения уровня доступа к данным в основных проектах .net? Есть другие решения для этого? Tnx заранее.

1 Ответ

0 голосов
/ 09 января 2019

Шаблоны Entity Framework и Repository полезны для манипулирования отдельными записями, например, интерактивной программы, в которой пользователь создает запись, редактирует поле, добавляет связанную запись и т. Д.

Если вы хотите импортировать любое количество записей без взаимодействия с пользователем, и EF, и шаблон репозитория добавляют так много дополнительных затрат, они бесполезны. EF сделает обход в базу данных для каждого изменения. Так что, если вы добавите записи по 300 тыс., Это будет 300 тыс. Поездок туда и обратно. Это безумие.

Вам нужна функция под названием BULK INSERT.

Обратитесь к классу SqlBulkCopy , чтобы сделать это в своем коде.

Каждая база данных имеет свой собственный инструмент для этого, поэтому вам нужно прочитать руководство по базам данных, но этот инструмент невероятно быстрый. Если вы можете использовать конкретный инструмент для своей базы данных, 300K записей должны занимать считанные секунды, а не минуты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...