Cannot refactor using LINQ to Entities and LinqKit / PredicateBuilder

I am trying to reorganize the LINQ expression into a method and have thrown the exceptions " Internal .NET Framework Data Provider error 1025. " and " The parameter 'xyz' was not bound in the specified LINQ to Entities query expression. ".

Here are the relevant parts of the entity model (using 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; } } 

The basic relational model is as follows:

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

I'm trying to create a query that, when searching for term will try to find the Place entity whose OfficialName starts with term OR, which has a PlaceName , whose Text or AsciiEquivalent starts with a search for term . ( Language not where I am having problems, although this is part of the request, because PlaceName should only match CultureInfo.CurrentUICulture.TwoLetterIsoLanguageName .)

The following code works :

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

What I'm trying to do next is reorganizing the NonOfficialNameMatches method to extract the name => ... expression into a separate method so that it can be reused by other queries. Here is one example I tried that does not work and throws an exception " 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) ) ); } 

When I don't have the .AsExpandable() chain in NonOfficialNameMatches , then I get the exception " Internal .NET Framework Data Provider error 1025. ".

I followed other advice here , for example with several combinations of calling .Expand() on predicates, but always ends with one of the above exceptions.

Is it even possible to split this expression into a separate method using LINQ to Entities with LinqKit / PredicateBuilder? If so, how? What am I doing wrong?

+6
source share
1 answer

The method below should work:

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

EDIT: Adding More Explanations

The PlaceNameMatches method works the way you wrote it. Your problems were how you used this method. If you want to separate the parts of the expression, follow the 3 steps that I did in the method above.

  • Set the local variable to the expression created by the method.

  • Set another local variable to a new expression that invokes the expression of the local variable.

  • Call the LinkKit Expand method: this will expand any Expression Called

+7
source

Source: https://habr.com/ru/post/916285/


All Articles