我正在从我的EF实体创建一个可重用的映射表达式到我的BLL实体:
private Expression<Func<Person, bool>> GetNameFilter(string name)
{
return person => person.Profile.UserName == name;
}
internal Expression<Func<Ef.Perk, Bll.Perk>> MapPerkPerk(string name)
{
return perk => new Bll.Perk
{
Id = perk.PerkId,
Name = perk.PerkName,
Description = perk.PerkDescription,
//Compilation Error
Owned = perk.Players.Any(GetNameFilter(name))
};
}
我在注意到的行上遇到了编译错误。错误如下:
ICollection不包含&#39;任何&#39;的定义。和最好的扩展方法重载&#39; Queryable.Any(IQueryable,Expression&gt;)&#39;需要一个类型为“IQueryable&#39;
的接收器
但是当我直接推送这个表达式时,这不会发生:
internal Expression<Func<Ef.Perk, Bll.Perk>> MapPerkPerk(string name)
{
return perk => new Bll.Perk
{
Id = perk.PerkId,
Name = perk.PerkName,
Description = perk.PerkDescription,
//No Compilation Error
Owned = perk.Players.Any(person => person.Profile.UserName == name)
};
}
为什么会这样?两个表达式的类型是相同的。
使用下面找到的LinqExpression解决方案,我现在在运行时收到以下错误:
类型&#39; System.InvalidCastException&#39;的例外情况发生在LinqKit.dll但未在用户代码中处理
附加信息:无法转换类型为&System; Linin.Expressions.InstanceMethodCallExpressionN&#39;的对象。输入&#39; System.Linq.Expressions.LambdaExpression&#39;。
internal FutureQuery<Perk> GetPlayerInfoPerks(string username)
{
return Master
.Perks
.VisiblePerks
.Select(Master.Perks.MapPerkPerk(username))
.Future();
}
这是由于使用了EntityFramework.Future库吗?
答案 0 :(得分:1)
为什么会这样?两个表达式的类型是相同的。
两个表达式的类型 不相同 - 它们看起来只是视觉上相同。以下是有效的:
dbContext.Persons.Any(GetNameFilter(name))
而这不是:
perk.Players.Any(GetNameFilter(name))
为什么呢?因为第一个需要Expression<Func<...>>
而第二个只需Func<..>
(IQueryable<T>
和IEnumerable<T>
方法之间的典型差异具有相同的名称)。希望你看到差异。当你直接输入它时,C#编译器会发出它的魔力来发出一个或另一个,但是当你手动执行它时,你应该使用正确的。
问题由LinqKit包与Invoke
/ Expand
自定义扩展方法(更常见的是AsExpandable
)解决。
对于您的具体示例,LinqKit解决方案可能是这样的:
using LinqKit;
...
internal Expression<Func<Ef.Perk, Bll.Perk>> MapPerkPerk(string name)
{
// LinqKit requires expressions to be in variables
var nameFilter = GetNameFilter(name);
return Linq.Expr((Ef.Perk perk) => new Bll.Perk
{
Id = perk.PerkId,
Name = perk.PerkName,
Description = perk.PerkDescription,
Owned = perk.Players.Any(p => nameFilter.Invoke(p))
}).Expand();
}