将LINQ子查询移动到扩展方法在运行时失败

3

我正在 LINQPad 中编写这个 LINQ 查询。我的操作类似于:

var perms = (from x in db.TableName // etc
            select new ProfilePermission
            { // etc
            });

perms = perms.Concat(from x in db.TableName // etc
            select new ProfilePermission
            { // etc
            });

var results = (from pi in db.AnotherTable
                where pi.IsActive
                select new MyViewModel
                {
                    KeyId = pi.Id,
                    Permissions = (from pm in perms
                                    where pi.ChildId == pm.ChildId
                                    select pm)
                }

使用这个子查询是可行的。因此,我想,将它移动到扩展方法中去。我尝试了以下代码:

public static IQueryable<ProfilePermission> GetProfilePermissions
    (
    this IMkpContext db
    )
{
    var perms = (from x in db.TableName // etc
            select new ProfilePermission
            { // etc
            });

    perms = perms.Concat(from x in db.TableName // etc
            select new ProfilePermission
            { // etc
            });


    return perms;
}

var results = (from pi in db.AnotherTable
                where pi.IsActive
                select new MyViewModel
                {
                    KeyId = pi.Id,
                    Permissions = (from pm in db.GetProfilePermissions()
                                    where pi.ChildId == pm.ChildId
                                    select pm)
                }

现在我收到一条消息:
NotSupportedException: LINQ to Entities不认识方法'System.Linq.IQueryable`1[PublicationSystem.Model.ViewModels.ProfilePermission] GetProfilePermissions(PublicationSystem.Model.IMkpContext)', 这个方法无法转换为存储表达式。
为什么子查询可以一种方式工作,而另一种方式却不能?我认为perms最终都会成为IQueryable<>

2
问题和解决方案在此处解释:http://www.albahari.com/nutshell/linqkit.aspx - Ivan Stoev
我通常只使用以下代码:public static object GetProfilePermissions。 - jdweng
1个回答

3
区别在于你使用扩展方法的地方,它不会被执行,而是成为另一个表达式(在你的情况下是Select)的一部分,即被记为无法被 EF 查询提供程序识别的方法的 MethodCallExpression
如果你确实在某个顶层查询结构(如JoinGroupJoin)中使用扩展方法,它将起作用。或者如果你可以将调用移动到查询之外并将结果存储到变量中。
例如,在你的情况下,以下代码将起作用:
var results = 
    from pi in db.AnotherTable
    where pi.IsActive
    join pm in db.GetProfilePermissions() on pi.ChildId equals pm.ChildId into permissions
    select new MyViewModel
    {
        KeyId = pi.Id,
        Permissions = permissions
    };

除此之外,还有这个:
var permissions = db.GetProfilePermissions();
var results =
    from pi in db.AnotherTable
    where pi.IsActive
    select new MyViewModel
    {
        KeyId = pi.Id,
        Permissions = (from pm in permissions
                        where pi.ChildId == pm.ChildId
                        select pm)
    };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接