Каковы наилучшие методы создания уровня доступа к данным для объекта, имеющего ссылку на другой объект?

#data-access-layer #business-logic

Вопрос:

(извините за мой английский) Например, в моем DAL у меня есть объект AuthorDB,у которого есть имя, и объект BookDB, у которого есть название и идентификатор автора.

Теперь, если я хочу показать все книги с соответствующим именем автора, я должен получить коллекцию всех книг и для каждой из них с атрибутом IdAuthor найти имя автора. Это создает множество запросов к базе данных, и, очевидно, можно использовать простое ОБЪЕДИНЕНИЕ.

Каковы мои варианты? Создание «пользовательского» объекта, содержащего имя автора и название книги? Если это так, то техническое обслуживание может стать ужасным.

Итак, какие есть варианты? Спасибо!

Ответ №1:

Не пишите что-то глючное, неэффективное и специализированное … когда доступны надежные, эффективные и универсальные инструменты. Бесплатно.

Выбери ОРМ. NHibernate, ActiveRecord, дозвуковой, NPersist, LinqToEF, LinqToSql, LLBLGenPro, DB4O, CSLA и др.

Ответ №2:

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

Ответ №3:

Если вы можете отделить запрос к базе данных от построения объекта, вы можете создать запрос для получения необходимых вам данных. Затем передайте эти данные своему разработчику, и пусть он вернет ваши книги.

С помощью Linq to SQL это можно сделать так же легко, как:

 public IEnumerable<Book> AllBooks()
{
    return  from book in db.Books
            join author in db.Authors on book.AuthorId equals author.Id
            select new Book() 
                        { 
                            Title = book.Title, 
                            Author = author.Name,
                        };
}
 

То же самое можно сделать с таблицами данных / наборами данных:

 public IEnumerable<Book> AllBooks()
{
    DataTable booksAndAuthors = QueryAllBooksAndAuthors(); // encapsulates the sql query

    foreach (DataRow row in booksAndAuthors.Rows)
    {
        Book book = new Book();
        book.Title = row["Title"];
        book.Author = row["AuthorName"];
        yield return book;
    }
}
 

Ответ №4:

Большое вам спасибо за ваш вклад.

На самом деле мы стараемся, чтобы объекты базы данных были как можно ближе к фактическим столбцам соответствующей таблицы в базе данных. Вот почему мы действительно не можем добавить (строковый) атрибут «Автор» в объект BookDB.

Вот проблема, которую я вижу при использовании объектов «Просмотр». В базе данных, если схема должна быть изменена по какой-либо причине (например: В таблице книг столбец «Заголовок» должен быть изменен для «The_Title», как нам легко узнать все объекты «Представления», которые необходимо изменить? Другими словами, как мне узнать, какие объекты должны быть изменены, когда они выполняют запросы, использующие несколько соединений?

Здесь, поскольку у нас есть объект AuthorsBooks, мы можем видеть по имени, что он, вероятно, делает запрос к таблицам книг и авторов. Однако с объектами, которые выполняют 4 или 5 соединений между таблицами, мы не можем полагаться на имя объекта.

Есть какие-нибудь идеи? (Еще раз спасибо, это отличный сайт!)

Ответ №5:

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

 var books = new BookRepository().GetAllBooks();
 

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