Должен ли я разделить DbContext на несколько наборов баз данных с сотнями тысяч записей в каждой из них?

#sql-server #entity-framework-core

Вопрос:

Мой вопрос: что определяет скорость(производительность) вызова метода DbContext.SaveChanges ()? И является ли плохой практикой помещать все наборы баз данных в один DbContext?

У меня есть основной проект c#/WPF/MS SQL Server/Entity Framework, который на самом деле предназначен для оптового бизнеса моей компании.

Я реализовал один DbContext, который содержит десятки наборов баз данных, каждый из которых, конечно же, представляет таблицу в базе данных. Существует около 10 основных таблиц, представляющих заказы, сведения о заказах, клиентов, продукты и т.д., И каждая из основных наборов баз данных/таблиц содержит от 50 000 до 150 000 записей. Проблема в том, что при вызове метода DbContext.SaveChanges выполнение занимает более 9000 мс(9 сек)! Я поместил ВСЕ наборы баз данных в один и тот же DbContext. Является ли это плохой привычкой и причиной низкой скорости?

Для теста я создал отдельный DbContext и поместил в него только один набор баз данных. Набор баз данных содержит около 100 000 записей, но вызов SaveChanges для этого занял около 500 мс, что было значительным улучшением.

Учитывая мою ситуацию, какова наилучшая практика для работы с базами данных? Пожалуйста, помогите.

 public class MyDbContext : DbContext
{
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseLazyLoadingProxies().UseSqlServer(DbConn.GetConnStr());
            base.OnConfiguring(optionsBuilder);
        }

        public DbSet<Order> Orders { get; set; }     // This has 100k  records.
        public DbSet<OrderDetail> OrderDetails { get; set; }     // This has 150k  records.
        public DbSet<Ship> Ships { get; set; }               // 100k  records
        public DbSet<ShipDetail> ShipDetails { get; set; }   // 150k  records
        public DbSet<Customer> Customers { get; set; }     // 100k records
        public DbSet<Product> Products { get; set; }       // 10k  records
        public DbSet<ProductStock> ProductStocks { get; set; }
        public DbSet<ProductPrice> ProductPrices { get; set; }
        public DbSet<PriceType> PriceTypes { get; set; }
        public DbSet<Claim> Claims { get; set; }
        public DbSet<Carrier> Carriers { get; set; }
        public DbSet<Channel> Channels { get; set; }
        public DbSet<Import> Imports { get; set; }
        public DbSet<ImportDetail> ImportDetails { get; set; }
}
 

Комментарии:

1. Количество наборов баз данных не имеет значения. Срок службы контекста и объем данных, которые вы загружаете в него, делают это. Возможно, вам следует более подробно рассказать об этих показателях.

2. Я создаю экземпляр DbContext при запуске, а затем передаю его всем классам и объектам. Я использую его на протяжении всего срока действия приложения. Может ли это быть причиной того, что он работает медленно?

3. Да, определенно.

4. Прочитайте это: Время жизни DbContext . Время жизни DbContext должно быть очень коротким.

Ответ №1:

Нет, совсем наоборот. Вы должны инкапсулировать одну базу данных на расширенный класс DbContext в своем приложении. Если это всего лишь одна бд ( или, скорее, одна схема), то вам вообще не следует разделять класс.

Вместо этого создайте partial класс и определите различные наборы баз данных в файлах, подобных домену, которые образуют конкретный класс.

Скорость зависит от изменений, внесенных в загруженные элементы x ( только абстрактные… ). Чем больше изменений, чем больше строк вы влияете/загружаете, тем сложнее становится.

Самым большим хитом для вас стали бы обновления sql. Если вы хотите управлять очень большими наборами данных, вообще не загружайте их в память. Работайте с ними .FromSqlRaw и делайте все на уровне бд, возвращая необходимый минимум. Например, массовые обновления-отличный пример для этого.

Также обратите внимание на случай, если вы загружаете ненужные объекты ( отношения, которые вы не используете).

Ответ №2:

Спасибо Герту Арнольду, рантри и Мкугиурису за ваши ответы и комментарии. Все вы абсолютно правы. Вот что я понял. Как вы все упомянули, проблема заключалась не в том, что в одном DbContext есть все таблицы. Проблема заключалась в том, что я использовал и передавал один «экземпляр» своего DbContext через несколько операций на протяжении всего срока службы приложения. Это НИКОГДА не следует делать с помощью DbContext.

Я решил, что DbContext должен быть создан для одной единицы работы или одной операции, а затем удалить экземпляр, как только операция закончится. Я считывал ВСЕ наборы данных в DbContext и запрашивал как можно больше с помощью одного экземпляра DbContext. Это гарантия низкой производительности.

Я сказал, что для сохранения изменений в базе данных потребовалось 9 секунд(9000 мс), вызвав SaveChanges. Теперь для выполнения той же работы требуется 250 мс(0,25 секунды). Надеюсь, мой комментарий поможет всем, у кого есть такая же проблема.