Какую стратегию DAL вы используете или предлагаете? - PullRequest
7 голосов
/ 14 июля 2009

Моя ситуация такова, что я облажался по существу. Я унаследовал свою базу кода около 1,5 лет назад, когда я занял эту позицию и вместо того, чтобы заново изобретать колесо, хотя теперь я знаю, что должен был это сделать, я сохранил DAL почти в той же структуре, что и предыдущий разработчик.

По сути, существует один файл (теперь с 15 тыс. Строк кода), который служит переходом к группе DAO, которые используют DataSets и TableAdapters для извлечения данных. Мои xsd-файлы выросли до такого размера, что они приводят к сбою R # в Visual Studio каждый раз, когда он открывается, и промежуточному классу, который теперь составляет 15 тыс. Строк, также требуется время для анализа R #. Не говоря уже о том, что это уродливо, оно работает, но не очень хорошо, и это абсолютный кошмар для отладки.

Пока что я пробовал переключиться на NHibernate. NHibernate - отличная библиотека, но, к сожалению, она не была достаточно адаптируемой для работы с моим приложением. Судя по словам ведущего разработчика (Фабио Мауло), это в значительной степени сочетание моих требований к приложению и ограничений на NHibernate при использовании удостоверений в качестве базы данных. ПК стратегия.

Так что теперь я вернулся к разработке собственного DAL. Я смотрю на несколько различных шаблонов для этого, но хотел бы получить ваши стратегии проектирования DAL. Есть так много способов и причин для реализации DAL определенным образом, поэтому, если вы могли бы объяснить вашу стратегию и почему она лучше всего подходит для вас, я был бы очень признателен.

Заранее спасибо!

Редактировать: Позвольте мне объяснить, почему NHibernate не работал, так как это, кажется, немедленный ответ. Мои пользователи создают «задание», которое на самом деле является временным представлением моего класса заданий. В рамках этой работы они дадут ей один или список весовых коэффициентов, которые также являются переходными на момент создания. Наконец, они предоставляют список рабочих деталей, с которыми связан определенный весовой коэффициент. Потому что в БД весовые коэффициенты уникальны, когда я продолжаю работать, и они каскадируются до весового коэффициента, который умирает, когда он находит дублирующий весовой коэффициент. Я попытался выполнить проверку перед назначением весового коэффициента для детали (что я не хотел делать, потому что я не хочу дополнительных вызовов к БД), но вызов CreateCriteria в NH также вызывает сброс в сеансе, в соответствии с Фабио, который разрушает мой кеш и таким образом убивает все в памяти представление задания. Люди в списке рассылки NH сказали, что я должен переключиться на GUID, но это невыполнимый вариант, поскольку процесс конвертации был бы кошмаром.

Ответы [ 7 ]

1 голос
/ 14 июля 2009

Мой опыт работы с NHibernate заключается в том, что, несмотря на то, что он обладает множеством функций и очень высокой производительностью, вам, в конечном счете, нужно стать экспертом NHibernate, чтобы исправить непредвиденное поведение. Прочитав ответы про-NHibernate и увидев

Хм, возможно, он использует долго работает Сессии (сессия на бизнес Модель транзакции), и в таком подход, используя идентичность обескуражен, так как это ломает ваши единичная работа (необходимо промыть напрямую после вставки новой сущности). Решение может быть, чтобы бросить идентичность и использовать идентификатор HiLo генератор.

иллюстрирует именно то, что я имею в виду.

Что я сделал, так это создал базовый класс, смоделированный несколько по шаблону ActiveRecord, от которого я наследую, и помечаю унаследованный класс с атрибутами, которые прикрепляют его к хранимой процедуре, каждый для выбора, вставки, обновления и удаления. Базовый класс использует Reflection для чтения атрибутов и назначения значений свойств класса параметрам SP, а в случае Select () присваивает значения столбца результирующего SQLDataReader свойствам списка обобщенных элементов.

Вот как выглядит DataObjectBase:

interface IDataObjectBase<T>
    {
        void Delete();
        void Insert();
        System.Collections.Generic.List<T> Select();
        void Update();
    }

Это пример класса данных, производных от него:

[StoredProcedure("usp_refund_CustRefundDetailInsert", OperationType.Insert)]
    [StoredProcedure("usp_refund_CustRefundDetailSelect", OperationType.Select)]
    [StoredProcedure("usp_refund_CustRefundDetailUpdate", OperationType.Update)]
    public class RefundDetail : DataObjectBase<RefundDetail>
    {

        [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
        [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Output)]
        [StoredProcedureParameter(null, OperationType.Select, ParameterDirection.Input)]
        [ResultColumn(null)]
        public int? RefundDetailId
        { get; set; }

        [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
        [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Input)]
        [StoredProcedureParameter(null, OperationType.Select, ParameterDirection.Input)]
        [ResultColumn(null)]
        public int? RefundId
        { get; set; }
        [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
        [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Input)]
        [ResultColumn(null)]
        public int RefundTypeId
        { get; set; }

        [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
        [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Input)]
        [ResultColumn(null)]
        public decimal? RefundAmount
        { get; set; }        
        [StoredProcedureParameter(null, OperationType.Update, ParameterDirection.Input)]
        [StoredProcedureParameter(null, OperationType.Insert, ParameterDirection.Input)]
        [ResultColumn(null)]
        public string ARTranId
        { get; set; }

    }

Я знаю, что, похоже, я заново изобретаю колесо, но все библиотеки, которые я обнаружил, либо слишком сильно зависели от других библиотек (например, ActiveRecord + NHibernate, что было довольно близко), либо были слишком сложны в использовании и администрировать.

Библиотека, которую я сделал, очень легкая (возможно, пара сотен строк C #) и не делает ничего, кроме как присваивает значения параметрам и выполняет SP. Он также очень хорошо подходит для генерации кода, поэтому в конечном итоге я не буду писать код доступа к данным. Мне также нравится, что он использует экземпляр класса вместо статического класса, так что я могу передавать данные в запросы без некоторого неудобного сбора критериев или HQL. Select () означает «стань больше как я».

1 голос
/ 14 июля 2009

Для меня лучше всего подойдет довольно простая концепция - используйте определения классов DAO и с помощью отражения создайте весь SQL, необходимый для их заполнения и сохранения. Таким образом, нет файла сопоставления, только простые классы. Моим DAO требуется базовый класс Entity, так что это не POCO, но это меня не беспокоит. Он поддерживает первичный ключ любого типа, будь то один столбец идентификаторов или несколько столбцов.

0 голосов
/ 19 августа 2009

Я использую мою оболочку для SP для быстрого получения данных и L2S, когда производительность не является целью Мой DAL использует шаблон хранилища и инкапсулированную логику для TDD.

0 голосов
/ 15 июля 2009

Linq to SQL хорошо, если вы используете SQL Server. Существует источник для поставщика LinqToSQL для доступа и MySQL. Я не проверял это все же. LinqToSql следует модели UnitOfWork, которая похожа на работу ADO.NET. Вы вносите серию изменений в локальную копию данных, а затем фиксируете все изменения одним вызовом обновления. Это довольно чисто, я думаю.

Вы также можете расширить класс DataRow самостоятельно, чтобы обеспечить строго типизированный доступ к вашим полям. Я использовал XSLT для генерации потомков DataRow на основе метаданных каждой таблицы. У меня есть общий потомок DataTable. MyDataTable где T - моя производная строка. Я знаю, что строго типизированные наборы данных MS делают то же самое, но я хотел облегченную универсальную версию, которую я полностью контролирую. Когда у вас есть это, вы можете написать статические методы доступа, которые запрашивают базу данных и заполняют DataTable.

Вы будете отвечать за запись изменений из DataTable обратно в DataSource. Я бы написал общий класс или метод, который создает обновление, вставляет и удаляет.

Удачи!

0 голосов
/ 14 июля 2009

Моим первым шагом было бы вырвать код из монстра 15 KLOC, а затем разработать стратегию создания нового DAL.

0 голосов
/ 14 июля 2009

В последних проектах мы перестали программировать отдельный DAL.

Вместо этого мы используем Object Relational Mapper (в нашем случае Entity Framework). Затем мы позволяем программе бизнес-уровня работать непосредственно с ORM.

В некоторых случаях это сэкономило нам более 90% усилий по разработке.

0 голосов
/ 14 июля 2009

Если ваш DAL записан на интерфейс, было бы намного проще переключиться на NHibernate или что-нибудь совместимое (я бы предпочел Fluent-NHibernate, но я отвлекся). Так почему бы не потратить время на рефакторинг DAL для использования интерфейса, а затем написать новую реализацию, используя NH или ваш ORM по вашему выбору?

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