我有一个使用LinqKit的EntityFramework 4.0的搜索仓库,具有以下搜索功能:
public IQueryable Search(Expression> predicate)
where T : EntityObject
{
return _unitOfWork.ObjectSet().AsExpandable().Where(predicate);
}另一个使用IQueryable返回值的类以不可能使用布尔LinqKit PredicateBuilder表达式的方式对查询进行子集化:
public IQueryable SubsetByUser(IQueryable set, User user)
where T : EntityObject
{
return set.Join(_searcher.Search((o) => o.UserGUID == user.GUID),
arc => arc.GUID,
meta => meta.ElementGUID,
(arc, meta) => arc);
}这里的问题是'T'作为EntityObject没有定义GUID,所以我不能使用它。对此的自然反应是实际定义SubsetByUser()方法以使用具有GUID属性的约束:
public IQueryable SubsetByUser(IQueryable set, User user)
where T : IHaveMetadata
{
return set.Join(_searcher.Search((o) => o.UserGUID == user.GUID),
arc => arc.GUID,
meta => meta.ElementGUID,
(arc, meta) => arc);
}但这不起作用。我正在使用LinqKit和Expandable()方法:
System.NotSupportedException: Unable to cast the type 'Oasis.DataModel.Arc' to
type 'Oasis.DataModel.Interfaces.IHaveMetadata'. LINQ to Entities only supports
casting Entity Data Model primitive types我需要返回一个IQueryable。我可以像这样做一个假的:
public IQueryable SubsetByUser(IQueryable set, User user)
where T : EntityObject
{
return set.AsEnumerable()
.Join(_searcher.Search((o) => o.UserGUID == user.GUID),
arc => arc.GUID,
meta => meta.ElementGUID,
(arc, meta) => arc)
.AsQueryable();
}当然,这当然是有效的,但这当然也是一种蝙蝠式的疯狂事情。 (我希望IQueryable的全部原因是在我们最终完成之前不执行查询。
我甚至试过这个:
public IQueryable SubsetByUser(IQueryable set, User user)
where T : EntityObject
{
return set.Join(_searcher.Search((o) => o.UserGUID == user.GUID),
arc => arc.GetType().GetProperty("GUID").GetValue(arc,null),
meta => meta.ElementGUID,
(arc, meta) => arc);
}它使用反射来获取Runs collection - 围绕编译器错误工作。我认为这很聪明,但是会导致LINQ异常:
System.NotSupportedException: LINQ to Entities does not recognize the
method 'System.Object GetValue(System.Object, System.Object[])' method,
and this method cannot be translated into a store expression.我也可以尝试改变搜索方法:
public IQueryable Search(Expression> predicate)
where T : IRunElement
{
return _unitOfWork.ObjectSet().AsExpandable().Where(predicate);
}但是这当然不会编译,因为IRunElement不是EntityObject,并且ObjectSet将T约束为一个类。
最后的可能性是简单地使所有参数和返回值IEnumerable:
public IEnumerable SubsetByUser(IEnumerable set, User user)
where T : EntityObject
{
return set.Join(_searcher.Search((o) => o.UserGUID == user.GUID),
arc => arc.GetType().GetProperty("GUID").GetValue(arc,null),
meta => meta.ElementGUID,
(arc, meta) => arc);
}其中也有效,但这又不允许我们延迟实例化,直到最后。
所以,似乎我没有办法做到这一点,而没有将所有东西都作为IEnumerable实例化,然后使用AsQueryable()返回它。有什么方法可以将这些放在一起,我失踪了吗?