我正在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.IQUERABLE`1[PublicationSystem.Model.ViewModels.ProfilePermission]GetProfilePermissions(PublicationSystem.Model.IMkpContext)",并且此方法无法转换为存储表达式。
为什么子查询以一种方式工作,而不是以另一种方式?我认为无论哪种方式,排列最终都是IQueryable<>
。
不同之处在于,在您使用扩展方法的地方,它不会被执行,而是成为另一个表达式(在您的情况下为Select
)的一部分,即作为MethodCallExpression
存储到EF查询提供程序无法识别的方法中。
如果您确实在一些顶级查询构造(如Join
或GroupJoin
)中使用了扩展方法,它就会起作用。或者,如果可以将调用移到查询之外,并将结果存储到变量中。
例如,在您的情况下,以下内容将起作用:
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)
};