【问题标题】:Can I create a LINQ-to-Entity query on non-Entity Member fields我可以在非实体成员字段上创建 LINQ-to-Entity 查询吗
【发布时间】:2011-08-04 23:58:32
【问题描述】:

我有一个实体类,我使用partial class 语法扩展了它以具有一些派生属性。我想使用IQueryable<T> 接口执行查询,该接口使用来自这些字段的信息,但我目前得到一个异常状态

指定的类型成员“标题”是 在 LINQ to Entities 中不受支持。 只有初始化器、实体成员和 实体导航属性是 支持。

这里是相关代码sn-ps。您可以假设 Entity 对象有一个名为 Id 的字符串成员。

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();
}

作为最后的手段,我总是可以在SkipTake 之前执行AsEnumerable(),但这将涉及从数据库中检索所有 对象,即使选择可以是由 SQL 完成。

也许最好的替代方法是使用反射来检查对象属性是否具有DataMemberAttribute,然后选择执行query.OrderBy().Skip().Take().AsEnumerable()query.AsEnumerable().OrderBy().Skip().Take()

【问题讨论】:

    标签: reflection entity-framework-4 linq-to-entities iqueryable dynamic-linq


    【解决方案1】:

    不,您不能,因为 linq-to-entities 查询只是转换为 SQL 的表达式树。要将树转换为 SQL,您需要使用实体映射,因为 Title 不在您的映射中,它会抛出异常。

    SkipTake 之前调用AsEnumerable 听起来是非常糟糕的设计,因为它总是会将整个数据表的内容传输到您的应用程序。这将非常缓慢,并且在大数据表的情况下也无用。

    如果这是本地化问题,您的数据库必须包含本地化字符串才能使其生效。同时,如果您只需要对少量记录执行此操作,则可以加载所有记录。

    【讨论】:

    • 预计数据集很小(最多只有数百条记录),因此加载所有项目是可以接受的折衷方案。
    • 数百条记录听起来不像是小数据。如果多个客户端同时请求这些数据,那将是很多数据。此外,对于 EF 上下文,由于物化默认跟踪等原因,数以百计的记录非常多。这些查询仍然可能很慢。
    • 这些记录通过 Dojo JsonRestStore 直接传递给 Web 客户端,因此我们在分离模式下运行。有没有办法让 EF 不创建跟踪信息而只返回处于分离状态的对象?
    • 是的。您必须首先从ObjectSet 中获取ObjectQuery 并将MergeOption 设置为MergeOption.NoTracking
    • 有没有人为这类问题找到可行的解决方案。我想要一个的原因是从 linq 语句中抽象出某些逻辑,即这样我就不会在所有地方重复业务逻辑。我一直在考虑这个问题的解决方案......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 2017-08-15
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    相关资源
    最近更新 更多