我有一个传递参数的服务,该参数要包含多少导航属性。基于布尔args,它连接一个实体列表以包括每个必需的外部实体。
在运行时,我不希望包含导航实体,也可以不包含多个导航实体。
我不能做的是使用.Include().Include
进行菊花链连接,因为我不知道传入的args中应该包含哪些和多少个。
我想实现这一目标,但似乎无法传递以逗号分隔的实体列表。有什么想法吗?
var res = db.Entity.Include(entityListCommaSeparated).Where(_=>_.ID == ID).FirstOrDefault();
答案 0 :(得分:0)
这看起来像一个存储库模式,如果要尝试从调用代码中“隐藏” 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()
的相关实体来组成并执行更有效的查询以填充ViewModel / DTO。 GetById可能在许多地方使用,因此我们可以减少重复并在存储库中支持它。我们不需要所有的筛选器方案等,调用者可以调用GetOrders,然后根据需要进行筛选。
如果仅返回DBSet,为什么还要打扰存储库?
List<TEntity>
并返回.AsQueryable()
。