Оптимизация Entity Framework (несколько запросов на модель в gridview)

Я работаю над приложением в WinForms. Мои данные хранятся на сервере MSSQL (Azure). Часть моего приложения включает в себя некоторые основные функции биллинга. Одна из имеющихся у меня моделей - это счета-фактуры, но я столкнулся с проблемой производительности. Мой первый вопрос: кто виноват? Мой плохо оптимизированный код или базовая структура сущностей. Основная проблема заключается в том, что я показываю список счетов в DataGridView. Для каждого счета, который я перечисляю, мне нужно сделать несколько вызовов DBContext. Это неуместно? По этой причине мне нужно сделать несколько звонков; один, чтобы получить список счетов для отображения (на основе идентификатора клиента FK), а затем для каждой модели счета я вызываю некоторые методы, которые вычисляют такие вещи, как SubTotal, TaxTotal и т. д. Эти функции приведены ниже.

    public decimal SubTotal()
    {

        decimal subtotal = 0;
        List<Billing_InvoiceItems> LineItems = db.Billing_InvoiceItems.Where(a => a.InvoiceID == this.id).AsNoTracking().ToList(); 
        {
        foreach (var LineItem in LineItems)
            subtotal += (LineItem.Cost * LineItem.Quantity);
        }

        return subtotal;
    }

    public decimal TaxTotal()
    {

        decimal taxtotal = 0;
        List<Billing_InvoiceItems> LineItems = db.Billing_InvoiceItems.Where(a => a.InvoiceID == this.id).AsNoTracking().ToList();
        foreach (var LineItem in LineItems)
        {
            if (LineItem.Taxable)
            {
                taxtotal += LineItem.Cost * (decimal) LineItem.TaxPercentage; 
            }
        }

        return taxtotal;
    }

    public decimal Total()
    {

        return (this.SubTotal() + this.TaxTotal());
    }

    public decimal TotalDue()
    {
        return (this.Total() - this.TotalPaid());
    }

    public decimal TotalPaid()
    {

        List<Billing_PaymentToInvoice> paymentsToInvoice = db.Billing_PaymentToInvoice.Where(a => a.InvoiceID == this.id).ToList();
        decimal totalpaid = 0;
        foreach (var Payment in paymentsToInvoice)
        {
            totalpaid += (decimal)Payment.AmountApplied;
        }

        return totalpaid;
    }

Я поступаю неразумно, когда мне нужно делать несколько SQL-запросов для каждого счета-фактуры, который я перечисляю? Или есть способ оптимизировать эти функции? Я пробовал один подход к кэшированию элементов счета (что позволяет мне вычислять итоги для отображения пользователю). Однако для этого мне потребовалось иметь функцию, которую я, по-видимому, часто вызывала, чтобы поддерживать кеш в актуальном состоянии.

Обновлено: вы увидите .AsNoTracking () там, в запросе LineItems, это была попытка оптимизировать его при поиске в Интернете.

Кеш должен это делать. Вы можете использовать разные модели кеширования, даже избегая полного пересчета сумм. (когда вы добавляете новый элемент, вы можете просто добавить стоимость к кэшированной общей стоимости). btw Существует агрегатная функция SQL SUM, но я не знаю, быстрее ли она, чем ваши вычисления.

Curly Brace 01.05.2018 15:13

Да, это действительно неэффективно. Вы можете получить все свои счета-фактуры и их отдельные позиции в вызове 1 db: var invoices = db.AsNoTracking().Invoice.Include(i => i.LineItems).Where(i => i.??? == xxx).ToList();. Теперь используйте это в модели памяти для выполнения расчетов и фильтрации. Такие вещи, как кеширование и AsNoTracking (), окажут гораздо меньшее влияние, чем минимизация ваших вызовов БД.

Steve Greene 01.05.2018 15:59

Позиции @SteveGreene хранятся в отдельной таблице, это имеет значение?

Eddie Fiorentine 01.05.2018 16:09

Не в правильно настроенной модели EF. У вас должна быть навигационная коллекция позиций под счетом. См., Например, здесь.

Steve Greene 01.05.2018 16:45

@SteveGreene - это проект Data-First, модели, созданные VS Scaffolding.

Eddie Fiorentine 01.05.2018 17:11

Затем он должен автоматически добавить коллекцию, если вы установили связь FK в базе данных.

Steve Greene 01.05.2018 17:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
33
0

Другие вопросы по теме