我有一个服务,传递参数,我想要包含多少导航属性。基于布尔args,它将实体列表连接起来以包含每个必需的外部实体。
在运行时,我想要包含没有导航实体或许多。我不能做的是与.Include().Include
的菊花链,因为我不知道基于传入args包含哪些以及包括多少。
我想实现这一点,但我似乎无法传入逗号分隔的实体列表。有任何想法吗?
var res = db.Entity.Include(entityListCommaSeparated).Where(_=>_.ID == ID).FirstOrDefault();
这看起来像一个存储库模式,如果你想尝试从调用代码中“隐藏”EF / DbContext,通常会变得混乱。
您可以考虑几个选项:
params Expression<Func<TEntity, object>>[] includes
,然后准备好在要返回多个实体时传递OrderBy表达式以及分页值。.Select()
。选项1:
public Order GetById(int id, params Expression<Func<Order, object>>[] includes)
{
var query = db.Orders.Where(x => x.ID == id);
// This part can be moved into an extension method or a base repository method.
if(includes.Any)
includes.Aggregate(query, (current, include) =>
{
current.Include(include);
}
// Don't use .FirstOrDefault() If you intend for 1 record to be returned, use .Single(). If it really is optional to find, .SingleOrDefault()
return query.Single();
}
//ToDo
public IEnumerable<Order> GetOrders(/* criteria?, includes?, order by?, (ascending/descending) pagination? */)
{ }
// or
public IEnumerable<Order> GetOrdersByCustomer(/* includes?, order by?, (ascending/descending) pagination? */)
{ }
// plus..
public IEnumerable<Order> GetOrdersByDate(/* includes?, order by?, (ascending/descending) pagination? */)
{ }
public bool CustomerHasOrders(int customerId)
{ }
public bool OrderExists(int id)
{ }
public int OrdersOnDate(DateTime date)
{ }
// etc. etc. etc.
请记住,这不会处理自定义的order by子句,并且返回实体列表的方法也需要这样。您的存储库也需要公开.Any()
(DoesExist)的方法,因为每个人都喜欢在每次返回时检查#null。 :)还有.Count()
。
选项2:
public IQueryable<Order> GetById(int id)
{
return db.Orders.Where(x => x.ID == id);
}
public IQueryable<Order> GetOrders()
{
return db.Orders.AsQueryable();
}
调用者可以在调用.Include()
之前找到他们想要的Linq和.Single()
,或者做一个.Any()
..他们可能不需要整个实体图,所以他们可以从实体和相关实体.Select()
没有.Include()
组成并执行更有效的查询来填充a ViewModel / DTO。 GetById可能会在很多地方使用,因此我们可以减少重复并在存储库中支持它。我们不需要所有过滤方案等,调用者可以调用GetOrders然后根据需要进行过滤。
如果只是返回DBSets,为什么还要使用存储库呢?
List<TEntity>
并返回.AsQueryable()
。