我有一个使用partial class
语法扩展的实体类,以具有一些派生属性。我想使用IQueryable<T>
接口执行查询,该接口使用来自这些字段的信息,但我目前得到一个异常,状态为
指定的类型成员'Title'是不支持LINQ到实体。只有初始化式、实体成员和实体导航属性是支持。
下面是相关的代码片段。你可以假设实体对象有一个名为Id
的String成员。
public partial class MyEntityObject
{
public String Title { get { return MyStrings.ResourceManager.GetString(Id) ?? ""; } }
}
/**
* Throws exception trying to sort on the 'Title' field of a 'MyEntityObject'
*/
public IEnumerable<T> Query<T>(String fieldName, int low, int high)
{
// Get the ObjectContext<T> using a Repository pattern
var query = context.GetRepository<T>()
// Create an OrderBy clause based on the field by dynamically building an expression tree
// see http://stackoverflow.com/questions/4546463/help-with-linq-and-generics-using-getvalue-inside-a-query
PropertyInfo propertyInfo = typeof(T).GetProperty(fieldName);
ParameterExpression e = Expression.Parameter(typeof(T), "e");
MemberExpression mexpr = Expression.MakeMemberAccess(e, propertyInfo);
IQueryable<T> sortedQuery = query.OrderBy(Expression.Lambda<Func<T,Object>>(mexpr, e));
return sortedQuery.Skip(low).Take(high - low + 1).AsEnumerable();
}
作为最后的手段,我总是可以在Skip
和Take
之前做AsEnumerable()
,但这将涉及从数据库中检索所有对象,即使选择可以由SQL完成。
也许最好的选择是使用反射来检查对象属性是否有DataMemberAttribute
,然后选择query.OrderBy().Skip().Take().AsEnumerable()
或query.AsEnumerable().OrderBy().Skip().Take()
?
不,你不能,因为链接到实体查询只是表达式树转换为SQL。为了将树转换为SQL,使用实体映射,因为Title
不在映射中,它将抛出异常。
在Skip
和Take
之前调用AsEnumerable
听起来是非常糟糕的设计,因为它总是将整个数据表的内容传输到应用程序。这将是非常缓慢的,在大数据表的情况下也是无用的。
如果这是本地化问题,您的数据库必须包含本地化字符串才能使其有效。同时,如果您只需要对少数记录执行此操作,则可以加载所有记录