【问题标题】:What are the best practices in creating a data access layer for an object that has a reference to another object?为引用另一个对象的对象创建数据访问层的最佳实践是什么?
【发布时间】:2010-09-16 16:49:26
【问题描述】:
(对不起我的英语)
例如,在我的 DAL 中,我有一个 AuthorDB 对象,它有一个名称
和一个 BookDB 对象,它有一个 Title 和一个 IdAuthor。
现在,如果我想显示所有带有相应作者姓名的书籍,我必须获取所有书籍的集合,并使用 IdAuthor 属性为每一本书找到作者姓名。这会对数据库进行大量查询,显然可以使用简单的 JOIN。
我有哪些选择?创建一个包含作者姓名和书名的“自定义”对象?如果是这样,维护可能会变得很糟糕。
那么,有哪些选择?
谢谢!
【问题讨论】:
标签:
data-access-layer
business-logic
【解决方案1】:
您可以在数据库中创建一个内置连接的视图并将一个对象绑定到该视图,例如作者图书数据库。它不会造成太严重的维护问题,因为视图可以隐藏任何底层更改并保持静态。
【解决方案2】:
如果您可以将数据库查询与对象构建分开,那么您可以创建一个查询来获取您需要的数据。然后将该数据传递给您的构建器并让它返回您的书籍。
使用 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,
};
}
同样可以使用 DataTables / DataSets 实现:
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;
}
}
【解决方案3】:
非常感谢您的意见。
实际上,我们正在尝试使数据库对象尽可能接近数据库中相应表的实际列。这就是为什么我们不能真正向 BookDB 对象添加(字符串)“作者”属性。
这是我在使用“视图”对象时看到的问题。在数据库中,如果出于任何原因必须修改架构(例如:在 Book 表中,必须为 'The_Title' 修改 'Title' 列,我们如何轻松知道必须修改的所有 'View' 对象?被修改?换句话说,当他们进行使用多个连接的查询时,我如何知道哪些对象必须被修改?
在这里,由于我们有一个 AuthorsBooks 对象,我们可以从名称中看出它可能会查询 book 和 author 表。但是,对于在表之间进行 4 或 5 个连接的对象,我们不能依赖对象名称。
有什么想法吗? (再次感谢您,这是一个很棒的网站!)
【解决方案4】:
当可靠、高效和通用的工具可用时,不要编写错误、低效和专业的东西。免费。
选择一个 ORM。 NHibernate、ActiveRecord、SubSonic、NPersist、LinqToEF、LinqToSQL、LLBLGenPro、DB4O、CSLA 等。
【解决方案5】:
我建议你看看领域驱动设计。在 DDD 中,您从存储库中获取所有业务对象。存储库隐藏了您的数据存储和实现,并将解决您在如何查询数据和跟踪数据库更改方面的问题。因为每个业务对象都是从存储库中检索的,所以存储库将是您的单点更改。然后,存储库可以以您认为有效的任何方式查询您的数据库,然后从该数据构建您的域对象:
var books = new BookRepository().GetAllBooks();
您应该能够使用 Justice 提到的任何技术对存储库进行编码。