dan*_*wig 6 linq-to-entities expression-trees predicatebuilder entity-framework-4 linqkit
我一直在尝试将LINQ表达式重构为一个方法,并且已经遇到了" Internal .NET Framework Data Provider error 1025.
"和" The parameter 'xyz' was not bound in the specified LINQ to Entities query expression.
"异常.
以下是实体模型的相关部分(使用EF 4.2/LINQ to Entities):
public class Place : Entity
{
public string OfficialName { get; protected internal set; }
public virtual ICollection<PlaceName> { get; protected internal set; }
}
public class PlaceName : Entity
{
public string Text { get; protected internal set; }
public string AsciiEquivalent { get; protected internal set; }
public virtual Language TranslationTo { get; protected internal set; }
}
public class Language : Entity
{
public string TwoLetterIsoCode { get; protected internal set; }
}
Run Code Online (Sandbox Code Playgroud)
基本关系模型是这样的:
Place (1) <-----> (0..*) PlaceName (0..*) <-----> (0..1) Language
Run Code Online (Sandbox Code Playgroud)
我想创建一个查询,将给出一个搜索时term
,试图找到Place
它的实体OfficialName
与开始term
或谁拥有PlaceName
它Text
或AsciiEquivalent
与搜索开始term
.(Language
不是我遇到麻烦的地方,虽然它是查询的一部分,因为PlaceName
s应该只匹配CultureInfo.CurrentUICulture.TwoLetterIsoLanguageName
.)
以下代码确实有效:
internal static IQueryable<Place> WithName(this IQueryable<Place> queryable,
string term)
{
var matchesName = OfficialNameMatches(term)
.Or(NonOfficialNameMatches(term));
return queryable.AsExpandable().Where(matchesName);
}
private static Expression<Func<Place, bool>> OfficialNameMatches(string term)
{
return place => place.OfficialName.StartsWith(term);
}
private static Expression<Func<Place, bool>> NonOfficialNameMatches(string term)
{
var currentLanguage = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
return place => place.Names.Any(
name =>
name.TranslationToLanguage != null
&&
name.TranslationToLanguage.TwoLetterIsoCode == currentLanguage
&&
(
name.Text.StartsWith(term)
||
(
name.AsciiEquivalent != null
&&
name.AsciiEquivalent.StartsWith(term)
)
)
);
}
Run Code Online (Sandbox Code Playgroud)
我接下来要做的是重构NonOfficialNameMatches
方法将name => ...
表达式提取到一个单独的方法中,以便其他查询可以重用它.这是我尝试过的一个例子,它不起作用并抛出异常" The parameter 'place' was not bound in the specified LINQ to Entities query expression.
":
private static Expression<Func<Place, bool>> NonOfficialNameMatches(string term)
{
return place => place.Names.AsQueryable().AsExpandable()
.Any(PlaceNameMatches(term));
}
public static Expression<Func<PlaceName, bool>> PlaceNameMatches(string term)
{
var currentLanguage = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
return name =>
name.TranslationToLanguage != null
&&
name.TranslationToLanguage.TwoLetterIsoCode == currentLanguage
&&
(
name.Text.StartsWith(term)
||
(
name.AsciiEquivalent != null
&&
name.AsciiEquivalent.StartsWith(term)
)
);
}
Run Code Online (Sandbox Code Playgroud)
当我没有.AsExpandable()
链NonOfficialNameMatches
,我得到" Internal .NET Framework Data Provider error 1025.
"例外.
我在这里遵循了其他建议,例如调用.Expand()
谓词的几种组合,但总是以上述异常之一结束.
甚至可以使用LINQ to Entities with LinqKit/PredicateBuilder将此表达式分解为单独的方法吗?如果是这样,怎么样?我究竟做错了什么?
以下方法应该有效:
private static Expression<Func<Place, bool>> NonOfficialNameMatches(string term)
{
Expression<Func<PlaceName, bool>> placeNameExpr = PlaceNameMatches(term);
Expression<Func<Place, bool>> placeExpr =
place => place.Names.Any(name => placeNameExpr.Invoke(name));
return placeExpr.Expand();
}
Run Code Online (Sandbox Code Playgroud)
编辑:添加其他说明
该PlaceNameMatches
方法与您编写时一样有效.您的问题在于您如何使用该方法.如果你想要分解表达式的部分,请遵循我在上面的方法中所做的3个步骤.
将局部变量设置为方法创建的表达式.
将另一个局部变量设置为调用局部变量表达式的新表达式.
调用LinkKit Expand
方法:这将扩展任何Invoked表达式
归档时间: |
|
查看次数: |
1213 次 |
最近记录: |