Что вернуть из DAL в BLL

В настоящее время у меня есть приложение, которое состоит из: Пользовательский интерфейс (веб-страница) BLL (объекты управления и домена) DAL (класс DataAccess для каждого из моих объектов домена).

В пользовательском интерфейсе я использую следующее для поиска объекта домена.

protect sub Button1_Click()
{
    IBook book = BookManager.GetBook(txtID.Text);
}

Вот мой BLL

public class BookManager 
{
    public static IBook GetBook(string bookId)
    {
        return BookDB.GetBook(bookId);
    }
}

public class Book : IBook
{
    private int? _id
    private string _name;
    private string _genre;

    public string Name
    {
        get { return _name; }
        private set 
        {
            if (string.IsNullOrEmpty(value))
                throw new Exception("Invalid Name");
            _name = value;
        }
    }

    public string Genre
    {
        get { return _serial; }
        private set 
        {
            if (string.IsNullOrEmpty(value))
                throw new Exception("Invalid Genre");
            _genre = value;
        }
    }

    // Other IBook Implementations

}

И наконец, вот мой DAL

public class BookDB
{
    public static IBook GetBook(int id)
    {
        // Get Book from database using sproc (not allowed to use any ORM)
        // ?? Create IBook Item?
        // return IBook
    }

Как создать объект IBook и вернуть его менеджеру? Я подумываю вернуть DataTable из BookDB в BookManager и создать объект Book и вернуть его, но это не кажется правильным. Есть ли другой способ сделать это?

Edit: Я решил разделить каждый слой на проект и столкнулся с проблемой циклической зависимости в слое DAL при попытке добавить ссылку на BLL. Я не могу получить доступ к классу книг или интерфейсу или что-либо в BLL из DAL. Должен ли я просто использовать объекты ado.net здесь и создать мой менеджер для создания фактического объекта из объекта ado.net? Вот как его выложили

BLL.Managers - BookManager
BLL.Interfaces IBook
BLL.Domain - Book
DAL - BookDB.

Спасибо!

Ответ 1

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

Вы заполняете объект из db, а затем отправляете его в BLL.

Если вы хотите сохранить объект, вы также отправляете его в BLL.

Ваши классы в BLL могут обернуть эти объекты, если это имеет смысл. Таким образом, легко просто отправить его обратно в DAL.

Dummy Book:

public class DummyBook:IBook 
{
    private nullable<int> _id;
    private string _name;
    private string _genre;

    public string Id
    {
        get {return _id;}
        set {_id = value;}
    }

    public string Name 
    {
        get {return _name;}
        set {_name = value;}
    }

    public string Genre 
    {
        get {return _genre;}
        set {_genre= value;}
    }

}

Книга DAL:

public class DALBook 
{
    public static IBook:GetBook(int id) 
    {
        DataTable dt;
        DummyBook db = new DummyBook();

        // Code to get datatable from database
        // ...
        // 

        db.Id = (int)dt.Rows[0]["id"];
        db.Name = (string)dt.Rows[0]["name"];
        db.Genre = (string)dt.Rows[0]["genre"];

        return db;
    }

    public static void SaveBook(IBook book) 
    {
        // Code to save the book in the database
        // you can use the properties from the dummy book
        // to send parameters to your stored proc.
    }
}

BLL Book:

public class Book : IBook
{
     private DummyBook _book;

     public Book(int id) 
     {
         _book = DALBook.GetBook(id);
     }

     public string Name 
     {
         get {return _book.Name;}
         set 
         {
            if (string.IsNullOrEmpty(value))
            {
                throw new Exception("Invalid Name");
            }
            _book.Name = value;
         }
     }

     // Code for other Properties ...



     public void Save()
     {
         // Add validation if required
         DALBook.Save(_book);
     }

}

Edit1:. Составы-фиктивные классы должны идти в своем собственном проекте (модель, как указано в комментариях в порядке). Ссылки будут работать следующим образом:

DAL Ссылки на проект модели.
BLL ссылается на модель и DAL.
Пользовательский интерфейс ссылается на BLL.

Ответ 2

BookDB должен возвращать экземпляр IBook. Мне нравится шаблон репозитория, который связан с отображением из db в домен.

Реализация репозитория возвращает экземпляры объектов домена. Это защищает остальную часть кода от конкретной реализации персистентности, на которую может влиять технология (тип базы данных, веб-сервис, [вставить что-то еще]) и формат, используемый для сохранения данных.

Ответ 3

Я бы, вероятно, использовал ExecuteReader для создания объекта в коде из базы данных. Причина этого в том, что у datatable больше накладных расходов, чем у читателя, поскольку он имеет больше функциональности (и, вероятно, был создан читателем). Поскольку вы не выполняете обновления/удаления с использованием datatable, вам не нужны служебные данные.

Как сказано, я бы поставил статический вспомогательный метод в классе BookManager.

internal static IBook BookFromReader(IDataReader reader)
{
     Book B = new Book();
     B.Prop = reader.GetString(0);
     B.Rinse = reader.Repeat();
     return B;
}

Причина этого в том, что причина, по которой у вас есть интерфейс, заключается в том, что вы можете изменить реализацию. Вы можете в будущем использовать INOVEL: IBook, IReference: IBook и т.д., А затем вы захотите создать абстрактную реализацию factory в вашем слое данных.

public static IBook GetBook(int id)
{
    // SqlCommand Command = new Command("SQL or sproc", ValidConnection);

    using(IDataReader DR = Command.ExecuteReader(id))
    {
        // checking omitted
        switch(DR.GetInt32(1))
        {
            case 0:
                 return BookManager.BookFromReader(DR);
            case 1:
                 return BookManager.NovelFromReader(DR);
            etc
        }
    }
}

Другим преимуществом DAL здесь является то, что вы можете кэшировать поисковые запросы. У вас может быть словарь, в котором хранятся книги, которые вы искали, чтобы уменьшить дополнительные вызовы db на объекты, которые вы уже вернули. Когда происходит обновление, вы удаляете кешированный объект... Это другое сообщение, хотя.

Если вы используете несколько сборок, интерфейсы и вспомогательные методы должны находиться в нейтральной (не зависимой) сборке. Сейчас в блоге-o-сфере происходит движение к меньшим количествам сборок, что означает меньше зависимостей и т.д.

Вот ссылка из блога, который я читал по этой теме: http://codebetter.com/blogs/patricksmacchia/archive/2008/12/08/advices-on-partitioning-code-through-net-assemblies.aspx

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

Удачи: -)

Ответ 4

По-моему, вы никогда не должны позволять DAL-доступу BLL. Это неоправданная зависимость.

Помещение класса Book в новый проект (возможно, с именем DomainModel) будет исправлять циклическую ссылку. Вы можете сделать что-то вроде этого:

Ссылка на проект BLL DAL и DomainModel

Ссылка на проект DAL DomainModel

Ссылка на проект UI BLL и DomainModel

Project DomainModel ничего не ссылается

Ответ 5

DataTable, который вы хотите вернуть, связан с базой данных, а для BLL не должно заботиться о том, какая база данных вы используете и что такое схема. Вы можете использовать DB-Object Mapper для сопоставления dbtable с объектом в DAL.

Ответ 6

Если вы не хотите возвращать DataTable, вы можете передать реализацию IBook из BookManager для заполнения DAL.

Ответ 7

Следовать за предполагаемой моделью. уровень доступа к данным (DAL) отвечает за получение и отправку данных из источника данных и из источника данных.

DAL не должен заботиться о каких-либо бизнес-единицах, которые BLL использует в качестве единственного задания, - это получить данные и вернуть их в нейтральный объект. Он должен быть нейтральным для общей совместимости, иначе вы могли бы не разделить слои по мере того, как преследуете цель.

Ваш бизнес-логический уровень (BLL) не должен заботиться о том, как DAL достигает получения или записи данных.

Для связи между BLL и DAL вы должны использовать нейтральные объекты.

Ваш BLL передает свойства объекта как отдельные параметры методам в DAL. параметры в DAL нейтральны, используя строки, int, bool, любые другие объекты .NET, которые не являются специфичными для версии базы данных, с которой вы общаетесь, и не являются конкретными типами, существующими только в вашем BLL.

DAL будет извлекать данные из когда-либо, когда-либо, и возвращать нейтральный объект данных вызывающему. Например, это может быть DataSet или DataTable или любой другой объект, не относящийся к используемому типу/версии базы данных. Следовательно, DataSet и DataTable являются объектами в пространстве имен System.Data, а не в пространстве имен System.Data.SQL и т.д.

В сущности: - BLL передает нейтральные типы в DAL (например: string, int, bool, long, float и т.д.). - DAL отвечает за преобразование этих типов в типы спецификаций базы данных, если это необходимо, прежде чем передавать их в источник данных DAL возвращает нейтральные типы данных в BLL (например, DataSet, DataTable и т.д.) - BLL несет ответственность за использование содержимого этих нейтральных типов данных для создания, заполнения и возврата особых бизнес-объектов

Ваш BLL должен ссылаться на ваш DAL. что он.

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