问题描述
比方说,我们在数据模型的四个实体:分类,书籍,作者和BookPages。此外,假设分类书籍,书籍,作者和图书,BookPages关系是一到多。
如果一个类别实体实例从数据库检索 - 包括书,Books.BookPages和Books.Authors - 这将成为一个严重的性能问题。此外,不包括它们将导致对象参考未被设置为一个对象的一个实例异常。
什么是使用多个包括方法调用的最佳做法?
- 写了一个方法GetCategoryById,包括里面的所有物品(性能问题)
- 写了一个方法GetCategoryById和发送的关系的列表,包括(也许,但似乎仍然没有足够的优雅)
- 写入方法,如GetCategoryByIdWithBooks,GetCategoryByIdWithBooksAndBooksPages和GetCategoryByIdWithBooksAndAuthors(不实用)
修改:由第二个选项我的意思是这样的:
公共静态范畴GetCategoryById(ModelEntities分贝,诠释的categoryId,PARAMS字符串[] includeFields)
{
VAR类别= db.Categories; 的foreach(在includeFields串includeField)
{
类别= categories.Include(includeField);
} 返回categories.SingleOrDefault(ⅰ= GT; i.CategoryId ==的categoryId);
}
当调用我们需要一个code是这样的:
类别theCategory1 = CategoryHelper.GetCategoryById(DB,5,书);
类别theCategory2 = CategoryHelper.GetCategoryById(DB,5,书,Books.Pages);
类别theCategory3 = CategoryHelper.GetCategoryById(DB,5,书,Books.Authors);
类别theCategory4 = CategoryHelper.GetCategoryById(DB,5,书,Books.Pages,Books.Authors);
有没有这种做法的任何明显的缺点?
A combination of these two is currently my approach. I know what properties I want to include for each context, so I rather hand-code them (as you said yourself, lazy-loading isn't always an option, and if it is, you'll repeat the same repetitive Include()
-like syntax when mapping from data models to DTO's).
This separation causes you to think harder about what datasets you want to expose, given data-access-code like this is usually hidden beneath a service.
By utilizing a base class containing a virtual method you can override to run the required Include()
s:
using System.Data.Entity;
public class DataAccessBase<T>
{
// For example redirect this to a DbContext.Set<T>().
public IQueryable<T> DataSet { get; private set; }
public IQueryable<T> Include(Func<IQueryable<T>, IQueryable<T>> include = null)
{
if (include == null)
{
// If omitted, apply the default Include() method
// (will call overridden Include() when it exists)
include = Include;
}
return include(DataSet);
}
public virtual IQueryable<T> Include(IQueryable<T> entities)
{
// provide optional entities.Include(f => f.Foo) that must be included for all entities
return entities;
}
}
You can then instantiate and use this class as-is, or extend it:
using System.Data.Entity;
public class BookAccess : DataAccessBase<Book>
{
// Overridden to specify Include()s to be run for each book
public override IQueryable<Book> Include(IQueryable<Book> entities)
{
return base.Include(entities)
.Include(e => e.Author);
}
// A separate Include()-method
private IQueryable<Book> IncludePages(IQueryable<Book> entities)
{
return entities.Include(e => e.Pages);
}
// Access this method from the outside to retrieve all pages from each book
public IEnumerable<Book> GetBooksWithPages()
{
var books = Include(IncludePages);
}
}
Now you can instantiate a BookAccess
and call methods on it:
var bookAccess = new BookAccess();
var allBooksWithoutNavigationProperties = bookAccess.DataSet;
var allBooksWithAuthors = bookAccess.Include();
var allBooksWithAuthorsAndPages = bookAccess.GetBooksWithPages();
In your case, you might want to create separate IncludePages
and GetBooksWithPages
-alike method pairs for each view of your collection. Or just write it as one method, the IncludePages
method exists for reusability.
You can chain these methods all the way you like, since each of them (as well as Entity Framework's Include()
extension method) returns yet another IQueryable<T>
.
这篇关于什么是多&QUOT的最佳做法;包括&QUOT;在实体框架-s?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!