Pregunta

He estado tratando de volver a factorizar una expresión LINQ en un método, y han estado funcionando en el "Internal .NET Framework Data Provider error 1025."y "The parameter 'xyz' was not bound in the specified LINQ to Entities query expression."las excepciones.

Aquí están las partes pertinentes de la entidad (modelo de uso de 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; }
}

El basic modelo relacional es este:

Place (1) <-----> (0..*) PlaceName (0..*) <-----> (0..1) Language

Estoy tratando de crear una consulta que, cuando se da una búsqueda term, trate de encontrar Place las entidades cuyos OfficialName se inicia con la term O que tiene un PlaceName cuya Text o AsciiEquivalent se inicia con la búsqueda term. (Language no es donde tengo problemas, aunque es parte de la consulta, porque PlaceNames sólo deben coincidir para que la CultureInfo.CurrentUICulture.TwoLetterIsoLanguageName.)

El siguiente código 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 estoy tratando de hacer ahora es refactorizar el NonOfficialNameMatches método para extraer el name => ... la expresión a cabo en un método independiente, de forma que pueden ser reutilizados por otras consultas.Aquí es un ejemplo que he probado, que no funciona y lanza 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 el .AsExpandable() de la cadena en NonOfficialNameMatches, luego me sale la "Internal .NET Framework Data Provider error 1025."la excepción.

He seguido otros consejos aquí como varias combinaciones de invocar .Expand() en los predicados, pero siempre terminan con una de las mencionadas excepciones.

Es incluso posible factor de esta expresión en un método independiente utilizando LINQ to entities con LinqKit / PredicateBuilder? Si es así, ¿cómo?¿Qué estoy haciendo mal?

¿Fue útil?

Solución

El siguiente método debería funcionar:

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();
}

EDITAR:La adición de más explicaciones

El PlaceNameMatches el método que funciona como usted lo escribió.Sus problemas fueron en cómo usted utiliza el método.Si desea factor de partes de una expresión que seguir los 3 pasos que hice en el método anterior.

  1. Establecer una variable local a la expresión creada por un método.

  2. Definir otra variable local a una nueva expresión que Invoca el local de expresión variable.

  3. Llame a la LinkKit Expand método:esto se expanda cualquier Invoca expresiones

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top