0

Hey I have following code:

    Func<Assoc, bool> predicate = (x) => 
    (
        !String.IsNullOrWhiteSpace(version) ? x.Version.Contains(version) : x.Version != null

    );

    var assocs = _context.Assoc
                    .Where(x => x.Model == model)
                    .Where(predicate)
                    ;

But it doesn't work. If I try to execute this server gives me Internal Server Exception but if I change this to

var assocs = _context.Assoc
      .Where(x => x.Model == model)
      .Where(x => x.Version.Contains(version))
;

it works as I expect.

Why is that?

Is it possible to get preview of Linq generated query?

Tseng
  • 61,549
  • 15
  • 193
  • 205
bielu000
  • 1,826
  • 3
  • 21
  • 45
  • 4
    EF cannot interpret your code you have to build an Expression, which can be translated into SQL. Maybe this helps you https://stackoverflow.com/questions/35346630/creating-dynamic-expression-for-entity-framework – Rand Random Aug 23 '17 at 07:09
  • Is there a need to use a predicate? you can always just use && to archive the same statement in Linq. e.g Make a method that will return a bool and just plug it into the && clause. – mahlatse Aug 23 '17 at 07:13
  • It would be great to use predicate because version is not required so I decided to use predicate as above. It's strange because in other method which is similar it works correctly – bielu000 Aug 23 '17 at 07:21
  • 1
    Please read @RandRandom linked article. You must pass an expression (`Expression>`) not a delegate (`Func`) for all `IQueryable`. For `IEnumerable` a delgate works too, because it does evaluates it in memory. But `IQueryable` needs to be translated to SQL, so it must be an expression – Tseng Aug 23 '17 at 07:25
  • Your error is coming from the brackets around the statement. It doesn't auto return without a return statement when you use the brackets. – Carl Pease Aug 23 '17 at 07:25
  • You should consult the documentation for the difference. In a nutshell, an expression describes code but do not executes it (unless you compile the expression to a delegate and invoke it), but an delegate is already compiled – Tseng Aug 23 '17 at 07:25

2 Answers2

0

Using LINQKit you can create predicates that will be expanded for you so you can use them in IQueryable expressions, but you don't need that for just excluding version testing.

var assocs = _context.Assoc
             .Where(x => x.Model == model);
if (!String.IsNullOrWhiteSpace(version))
    assocs = assocs.Where(x.Version.Contains(version));
NetMage
  • 26,163
  • 3
  • 34
  • 55
-1

becuse the EF can translate Contains method to sql (Version LIKE '%@version%'), but no evaluate your "external" function.

if you load the result to memroy (by export method as ToList()) you can do it as linq2object:

var assocs = _context.Assoc.ToList()
                .Where(x => x.Model == model)
                .Where(predicate);

My code shows and illustrates but it is definitely not recommended, because it is better to question the DB than to work on memory.

dovid
  • 6,354
  • 3
  • 33
  • 73
  • 1
    Why provide an answer that you dont recommend? – Rand Random Aug 23 '17 at 07:29
  • @RandRandom beacuse i think the question is **why**. – dovid Aug 23 '17 at 09:05
  • Shouldn't you at least put the `ToList` after the first `Where`? – NetMage Aug 23 '17 at 18:24
  • The `ToList` here does nothing but prevent the first filter from being applied. The second filter, not being an `Expression`, was never being provided to the query provider in the first place, and so the provider isn't going to fail to translate it (it's not even going to try). – Servy Aug 23 '17 at 19:12