He intentado refactorizar una expresión LINQ en un método, y me he estado ejecutando en las excepciones "Internal .NET Framework Data Provider error 1025.
" y "The parameter 'xyz' was not bound in the specified LINQ to Entities query expression.
".No se puede refactorizar utilizando LINQ para Entidades y LinqKit/PredicateBuilder
Estas son las partes relevantes del modelo de entidad (usando EF 4.2/LINQ a Entidades):
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; }
}
El modelo relacional básica es la siguiente:
Place (1) <-----> (0..*) PlaceName (0..*) <-----> (0..1) Language
Estoy tratando de crear una consulta que, cuando se da una búsqueda term
, intente encontrar entidades cuyo OfficialName
comienza con term
O que tiene PlaceName
cuyo Text
o AsciiEquivalent
comienza con la búsqueda term
. (Language
no es donde yo estoy teniendo problemas, a pesar de que es parte de la consulta, porque PlaceName
s sólo deben coincidir para que la CultureInfo.CurrentUICulture.TwoLetterIsoLanguageName
.)
El código siguiente Cómo funciona:
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)
)
)
);
}
Lo que trato de hacer a continuación es refactorizar el método NonOfficialNameMatches
para extraer la expresión name => ...
en un método separado, para que pueda ser reutilizada por otras consultas. He aquí un ejemplo que he tratado, que no funciona y produce la excepción "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)
)
);
}
Cuando no tengo la cadena .AsExpandable()
en NonOfficialNameMatches
, entonces me sale el' Internal .NET Framework Data Provider error 1025.
" excepción.
He seguido other advice here como varias combinaciones de invocación de .Expand()
en los predicados, pero siempre acabo con una de las excepciones antes mencionadas.
¿Es posible factorizar esta expresión en un método separado utilizando LINQ para Entidades con LinqKit/PredicateBuilder? Si es así, ¿cómo? ¿Qué estoy haciendo mal?
+100, gracias Estaba empezando a pensar en esta pregunta nunca son respondidas. La explicación adicional ayuda también. – danludwig