我一直在嘗試將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; }
}
基本關係模型是這樣的:
Place (1) <-----> (0..*) PlaceName (0..*) <-----> (0..1) Language
我正在嘗試創建一個查詢,當給定搜索term
,嘗試查找其中OfficialName
以term
OR開頭的Place
實體,其中PlaceName
的Text
或AsciiEquivalent
以搜索term
開頭。 ( Language
不是我遇到麻煩的地方,雖然它是查詢的一部分,因為PlaceName
應該只匹配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)
)
)
);
}
我接下來要做的是重構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)
)
);
}
當我沒有.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();
}
編輯:添加其他說明
PlaceNameMatches
方法在您編寫時起作用。您的問題在於您如何使用該方法。如果你想要分解表達式的部分,請遵循我在上面的方法中所做的3個步驟。
將局部變量設置為方法創建的表達式。
將另一個局部變量設置為調用局部變量表達式的新表達式。
調用LinkKit Expand
方法:這將擴展任何Invoked表達式