2014-01-11 14 views
2

Я занимаюсь преобразованием большого классического ASP-приложения в ASP.Net MVC с использованием подхода n-уровня. В моем DAL я использую ADO.Net для запроса базы данных и преобразования запросов в объекты. У меня также есть BLL для таких вещей, как вычисления и валидация.Расчеты в слое доступа к данным

Мой вопрос касается выполнения вычислений в DAL, когда необходимы вычисления для преобразования запроса в объекты. Чтобы дать пример рассмотрит систему выставления счетов-фактур с итоговой информацией, а также позиции:

public class Invoice 
{ 
    public int InvoiceID { get; set; } 
    public DateTime InvoiceDate { get; set; } 
    public decimal InvoiceTotal { get; set; } 
    public List<InvoiceLineItem> LineItemList { get; set; } 
} 

Так что мой код для преобразования позиции в запросе к базе данных будет выглядеть следующим образом:

decimal InvoiceTotal = 0; 
var LineItem = new InvoiceLineItem(); 
while (Reader.Read()) 
{ 
    LineItem.ItemID = Extensions.SafeGetInt(Reader, "ItemID"); 
    LineItem.Price = Extensions.SafeGetDecimal(Reader, "Price"); 
    LineItem.Quantity = Extensions.SafeGetInt(Reader, "Quantity"); 
    LineItemList.Add(LineItem); 

    InvoiceTotal = InvoiceTotal + (LineItem.Price * LineItem.Quantity);  
} 

Invoice.InvoiceTotal = InvoiceTotal; 
etc ... 

Так вот мой вопрос: учитывая мою n-ярусную архитектуру, является ли мое DAL правильным местом для выполнения расчета InvoiceTotal? Учитывая, что часть работы BBL заключается в выполнении расчетов, нарушает ли это разделение проблем между DAL и BLL? Или я беру функцию BBL для выполнения вычислений слишком буквально, и нормально делать вычисления в DAL, если эти вычисления необходимы для заполнения модели? Одна из причин, почему я считаю целесообразным делать расчет InvoiceTotal в DAL, заключается в том, что мне нужно только один раз перебирать записи элементов счета. Если бы я создал отдельную функцию InvoiceTotal в другом месте, чтобы получить InvoiceTotal, тогда мне пришлось бы повторять итерацию по записям во второй раз.

Редактировать: Оказывается, что реальный вопрос заключается не в том, должны ли вычисления быть допустимыми в DAL, а в том, должен ли InvoiceTotal быть в моей модели вообще. С точки зрения нормализации базы данных это не требуется, потому что итоговые суммы могут быть рассчитаны из позиций. В этом случае InvoiceTotal не должен находиться в моей модели, но должен быть в моей модели ViewModel, и в этом случае нет необходимости делать вычисления в моем DAL. Я мог игнорировать проблемы с нормализацией базы данных по причинам производительности и включать InvoiceTotal в мою модель, но если это так, я бы сохранил InvoiceTotal в базе данных, и в этом случае при заполнении моей модели никакие вычисления не потребовались бы, так как я просто вытащил бы значение из базы данных.

Извлеченный урок: если у меня возникает соблазн выполнять вычисления в моем DAL, моя модель, скорее всего, будет испорчена.

+0

Средний процессор, возможно, выполняет миллионы итераций в секунду. Это не должно диктовать вашу архитектуру; вычисления относятся к бизнес-уровню. – CodeCaster

+0

Расчеты относятся к бизнес-уровню. Данные Persisting and Querying относятся к слою данных. – MUG4N

+0

CodeCaster, я также пытаюсь быть СУХОЙ. Если я создам отдельную функцию для вычисления суммы счета и повторного повторения записей, я не нарушаю DRY? –

ответ

3

Я хотел бы добавить вычисления в слой бизнес-логики

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

Еще одна веская причина добавить его на уровень бизнес-логики заключается в том, что он может быть получен из данных линии, возвращаемых из DAL, который будет поддерживать слой DAL, сосредоточенный на записи и чтении данных. Это также позволяет вам рассчитывать в одном месте.

Однако, поскольку суммы счетов фиксируются после отправки, вы можете написать начальное значение при первом сохранении, а затем разрешить ручную поправку. В этом случае общий расчет счета будет выполнен на бизнес-уровне, но значение также будет записано и извлечено из базы данных без пересчета.

+0

На самом деле, я считаю, что моя ошибка заключается в том, что InvoiceTotal не должен находиться в модели вообще, но только в ViewModel (например, InvoiceViewModel). С точки зрения нормализации базы данных нет оснований для сохранения счета-фактуры Total в базе данных, поскольку он может быть рассчитан из позиций. Если я решил не включать InvoiceTotal в свою модель и использовать ее только в моей модели ViewModel, тогда становится ясно, что InvoiceTotal должна быть отдельной функцией, поскольку она не будет в InvoiceModel. –

+0

Я согласен с общей суммой счета-фактуры. При общей валовой сумме расчет будет содержать некоторый элемент налога, который может быть изменен в будущем. В этом случае я определенно напишу его в базу данных. –

+0

Вы получаете очки, потому что ваш ответ заставил меня увидеть, что моя модель ошибочна –