2009-11-02 9 views
7

Tengo una consulta LINQ que se ve algo como esto:LINQ: función lógica simple devuelve LINQ Excepción

var query = from x in table where SomeFunctionReturnsBool() select; 

private bool SomeFunctionReturnsBool() 
{ 
    return true; 
} 

Esto devuelve una excepción y dice que "no tiene traducción SomeFunctionReturnsBool apoyado a SQL". Entiendo que esto es porque quiere tratar "SomeFunctionReturnsBool" como una expresión para evaluar como SQL, pero no puede.

Aunque esta consulta Linq no es complicada, las verdaderas son. ¿Cómo puedo lograr lo que estoy tratando de hacer aquí, que es dividir partes de la consulta para que sea más legible?

Jeff

ACTUALIZACIÓN buenas respuestas. Estoy intentando ahora a trabajar con expresiones lugar, pero este código me consigue "no puede resolver método Dónde (expresión lambda)":

var query = from x in table where SomeFunctionReturnsBool() select x; 

private Expression<Func<EligibilityTempTable, bool>> SomeFunctionReturnsBool 
{ 
    return (x) => true; 
} 
+0

respondido al comentario de, muestra una forma (dudosa) de la utilización de este enfoque con la sintaxis de consulta. –

Respuesta

7

Otra forma es utilizar Expression<Func<YourType, bool>> predicado ...

var query = from x in table where SomeFunctionReturnsBool() select; 

Editar: No suelo hacerlo de la manera que he demostrado más arriba ... Estaba llegando que desde el código encima. Esta es la forma en que generalmente lo implemento. Porque entonces puedes agregar más métodos Enumerable o comentarlos durante la depuración.

var results = table.Where(SomeFunctionReturnsBool()) 
    .OrderBy(yt => yt.YourProperty) 
    //.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts... 
    //.Take(pageSize) 
    .ToList(); //Finally executes the query... 

private Expression<Func<YourType, boo>> SomeFunctionReturnsBool() 
{ 
    return (YourType yt) => yt.YourProperty.StartsWith("a") 
     && yt.YourOtherProperty == true; 
} 

yo prefiero usar el PredicateBuilder que le permite construir una expresión que se utiliza en el caso de ...

+1

+1 para PredicateBuilder. Eso es muy bonito. – Tinister

+0

Por alguna razón, hacer esto causa el error donde "no se puede resolver el método donde (expresión lambda)" – jlembke

+0

No estoy seguro de por qué obtuve el -2 sea bueno si tuviera "tiempo" para explicar su voto negativo ... – bytebender

3

Usted puede hacer esto en LINQ a SQL mediante la creación de una UDF asigna a la contexto de datos; esto implica escribir TSQL y usar ctx.SomeFunctionblah (...).

La alternativa es trabajar con los árboles de expresión - por ejemplo, podría ser:

Expression<Func<Customer, bool>> SomeFunc() { 
    return c => true; // or whatever 
} 

y utilizar .Where(SomeFunc()) - es que lo suficientemente cerca? No se puede utilizar la sintaxis de consulta en este caso, pero hace el trabajo ...


Añadido poco fiables Where método para mostrar cómo se puede utilizarlo en la sintaxis de consulta. I no haga sugiera que esto es fantástico, pero puede que lo encuentre útil.

using System; 
using System.Linq; 
using System.Linq.Expressions; 

static class Program 
{ 
    static void Main() 
    { 
     using (var ctx = new NorthwindDataContext()) 
     { 
      ctx.Log = Console.Out; 
      // fluent API 
      var qry = ctx.Customers.Where(SomeFunc("a")); 
      Console.WriteLine(qry.Count()); 

      // custom Where - purely for illustration 
      qry = from c in ctx.Customers 
        where SomeFunc("a") 
        select c; 
      Console.WriteLine(qry.Count()); 
     } 
    } 
    static IQueryable<T> Where<T>(this IQueryable<T> query, 
     Func<T, Expression<Func<T, bool>>> predicate) 
    { 
     if(predicate==null) throw new ArgumentNullException("predicate"); 
     return query.Where(predicate(default(T))); 
    } 
    static Expression<Func<Customer, bool>> SomeFunc(string arg) 
    { 
     return c => c.CompanyName.Contains(arg); 
    } 
} 
+0

guau, genial Marc, no sabía de esto. Verifique mi respuesta a continuación ... es útil, pero esto es genial. gracias – andy

+0

Solo para aclarar, Marc. Si utilizo el árbol de expresiones como lo tiene aquí, ¿tengo que usar la sintaxis lambda y no la sintaxis de consulta? – jlembke

+0

Agradable. Ok, voy a trabajar con eso. – jlembke

0

No utilice la sintaxis de la consulta para esto.

var query = table.Where(x => SomeFunction(x)); 
+0

Eso no ayudará con LINQ-to-SQL; todavía no hay traducción para 'SomeFunction'. –

+0

sí, no hay diferencia entre esto y la sintaxis de la consulta – andy

+0

sí, esto es lo mismo ... – jlembke

1

me acaba de romper a cabo de esta manera:

Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true; 

var query = from x in table where someTreeThatReturnsBool select x; 

Se puede crear funciones que pasan alrededor de los árboles de expresión.

2

Básicamente, "listo para usar", no puede tener consultas de ejecución de LINQ-to-SQL que tengan funciones personalizadas en ellas. De hecho, solo se pueden usar algunos métodos nativos que se pueden traducir a SQL.

La forma más sencilla de evitar esto puede afectar lamentablemente el rendimiento en función de la cantidad de datos que trae de la base de datos.

Básicamente, solo puede usar funciones personalizadas en sentencias WHERE si los datos ya se han cargado en la memoria, es decir, SQL ya se han ejecutado.

La solución más rápida para que su ejemplo se vería así:

var query = from x in table.ToList() where SomeFunctionReturnsBool() select; 

Aviso del ToList(). Ejecuta el SQL y pone los datos en la memoria. Ahora puede hacer lo que quiera en la declaración/método WHERE.

+2

Verdadero ... pero luego está retirando todos los registros y luego haciendo el filtrado en la memoria frente a hacer en el servidor de la base de datos . – bytebender

+0

De acuerdo (con J.13.L) - usar 'ToList()' suele ser una mala forma de hacerlo, y solo funciona con volúmenes de datos pequeños. –

+0

Me encantaría evitar tirar todo esto. Montones de datos. Gracias a Andy – jlembke

Cuestiones relacionadas