动态OrderBy()使用不在DB中的属性会引发异常

时间:2015-09-11 20:01:41

标签: c# entity-framework linq

我有以下型号:

public class User
{
    public string UserId { get; set; }
    public string UserName { get; set; }
    public List<Membership> Membership { get; set; }
    public bool IsRegistered
    {
        get { return !String.IsNullOrEmpty(UserName); }
    }
}

public class Membership
{
    public string MembershipId { get; set; }
    public User User { get; set; }
}

在我的Membership实体的存储库中,我尝试通过执行entriesIQueryable<Membership>orderBy的{​​{1}}来执行以下操作来订购我的收藏集LamdaExpression等于{ x => x.User.IsRegistered }

ordered = Queryable.OrderBy(ordered, orderBy);

当我尝试这个时,我收到以下错误:

  

指定的类型成员&#39; IsRegistered&#39; LINQ不支持   实体。仅初始化程序,实体成员和实体导航   支持属性。

如何通过不在数据库中的属性来订购我的收藏?

提前致谢。

3 个答案:

答案 0 :(得分:3)

由于IsRegistered是客户端函数,因此您需要使用LINQ over objects进行排序。您可以将LINQ over SQL转换为LINQ over objects,方法是枚举它。然后,一旦它是一个LINQ over对象,你就可以使用LINQ over itect的OrderBy来命令它。这样做的常用方法是调用ToList,如:

ordered = Queryable.ToList().OrderBy(ordered, orderBy);

如果要对数据库进行排序,则需要将客户端代码转换为与SQL兼容的代码,例如:

ordered = Queryable.OrderBy(ordered, (x=>x.User.UserName!=null && x.User.UserName!=''));

答案 1 :(得分:2)

您始终可以在本地进行排序。如果您希望将计算属性用于服务器端排序,则需要一个LINQ提供程序(EF)可以转换的表达式(在您的情况下为SQL)。

对于!String.IsNullOrEmpty(UserName),您可以使用适用于LINQ2SQL的m=>String.Empty!=(m.User.UserName??String.Empty)。检查生成的SQL时,您应该得到类似

的内容
-- Region Parameters
DECLARE @p0 NVarChar(1000) = ''
DECLARE @p1 NVarChar(1000) = ''
-- EndRegion
SELECT --fields
FROM [Membership] as [t0]
JOIN User AS [t1] 
ON -- id
WHERE -- your predicate
ORDER BY 
(CASE 
    WHEN @p0 <> (COALESCE([t1].[UserName],@p1)) THEN 1
    WHEN NOT (@p0 <> (COALESCE([t1].[UserName],@p1))) THEN 0
    ELSE NULL
END)

我想EF也会翻译它。

答案 2 :(得分:0)

你做不到。实体框架的order by映射到db字段,因为它在SQL端调用“ORDER BY”子句。

如果你真的想通过非db字段订购你的记录(但是,据我所知,你可以在这种情况下通过UserName订购你的记录),你应该过滤你的记录,调用ToList()和OrderBy(很明显这只是从数据库服务器返回结果后的记录顺序)。