2012-07-26 45 views
6

Estoy tratando de hacer una consulta que no incluye valores repetidos IdUser, pero no funciona.LINQ seleccionar distinto C#

esta es mi LINQ consulta:

var sql= (from u in db.USER 
      join c in db.CONSULT on u.IdUser equals c.IdUser 
      select new UsuersViewModel 
       { 
        IdUser = c.IdUser, 
        DateCreate=c.DateCreate, 
        IdTypeConsult = c.IdTypeConsult, 
        Sex=u.Sex 
       }) 
       .Distinct(); 

quiero esto:

SELECT distinct CONSULT.IdUser , CONSULT.DateCreate, 
     CONSULT.IdTypeConsult , USER.Sex 
FROM CONSULT INNER JOIN 
     USER ON CONSULT.IdUser = USER.IdUser 

La consulta hacerle registros duplicados

¿Por qué no funciona?

+1

usted no está dando nada a 'distinta' sucesivamente. :) –

+0

Proporcione algunos datos de muestra? – Bert

+4

Por favor amplía "No funciona" ... ¿Te da duplicados? ¿No devuelve nada? ¿El conjunto no definido (antes del 'Distinct()' contiene lo que cabría esperar? Sin saber el problema, es difícil adivinar qué está yendo mal ... – Chris

Respuesta

2

Al comparar instancias de clase (frente a tipos anónimos) debe definir "igualdad". Para los tipos anónimos, el compilador asume que la igualdad significa que "todos los campos son iguales", como SQL. Por lo que tiene algunas opciones:

  1. Use un tipo anónimo en la consulta, utilice .Distinct(), y convertir a un tipo fuerte después,
  2. definir una clase IEqualityComparer<Usuers> y pasar eso a Distinct,
  3. Anulación Equals (y GetHashCode) en Usuers

2) y 3) será un código muy similar. 2) es más flexible (puede definir la igualdad de diferentes maneras definiendo diferentes clases, mientras que 3) se usará cada vez que compare Uusers insatnces (no solo en esta consulta).

Ver mi respuesta a un problema similar here.

+0

Ni siquiera había notado que el código original estaba usando un tipo definido en lugar de una anónima. Era solo la segunda vez que volvía a leer * después de * leer esta publicación. Me di cuenta. Buen trabajo al detectar eso. :) – Chris

7

Creo que desea utilizar la sobrecarga Distinct(IEqualityComparer<T>). Es necesario crear un IEqualityComparer a hacer lo que quiera:

class UserComparer : IEqualityComparer<UsuersViewModel > 
{ 
    public bool Equals(UsuersViewModel x, UsuersViewModel y) 
    { 
     //Check whether the compared objects reference the same data. 
     if (Object.ReferenceEquals(x, y)) return true; 

     //Check whether any of the compared objects is null. 
     if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
      return false; 

     return x.IdUser == y.IdUser; 
    } 

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects. 

    public int GetHashCode(UsuersViewModel user) 
    { 
     //Check whether the object is null 
     if (Object.ReferenceEquals(user, null)) return 0; 

     return user.IdUser == null ? 0 : user.IdUser.GetHashCode(); 
    } 
} 

Entonces utilizar de esta manera:

var comparer = new UserComparer(); 
var sql= (from u in db.USER 
      join c in db.CONSULT on u.IdUser equals c.IdUser 
      select new UsuersViewModel 
       { 
        IdUser = c.IdUser, 
        DateCreate=c.DateCreate, 
        IdTypeConsult = c.IdTypeConsult, 
        Sex=u.Sex 
       }) 
       .Distinct(comparer); 

No estoy seguro de si eso va a generar el SQL que desea, pero probablemente a conseguir los resultados que quieres

+0

no funciona :(, ¿falta el código? – kalu

+0

Editado el código; asume que ha eliminado al Usuario como Usuers. Si ese no es el caso, reemplace "Usuario" por "Usuers" –

+0

indica un error en '.Distinct (comparador);' – kalu

0

Nota: Lo siguiente se puede ejecutar en LinqPad (gratis en http://www.linqpad.net/) - simplemente configure el menú desplegable Idioma en "Programa C#" y pegue el código en la ventana del editor.

Puede utilizar "grupo" para proporcionar sus necesidades distinta de la siguiente manera:

void Main() 
{ 
    var db = new DataBase(); 
    var sql= (from u in db.USER 
      join c in db.CONSULT on u.IdUser equals c.IdUser 
      group c by new { c.IdUser, c.DateCreate, c.IdTypeConsult, u.Sex } into gc 
      select new UsuersViewModel 
       { 
        IdUser = gc.Key.IdUser, 
        DateCreate=gc.Key.DateCreate, 
        IdTypeConsult = gc.Key.IdTypeConsult, 
        Sex=gc.Key.Sex 
       }) 
       .Distinct(); 
    sql.Dump("SQL Distinct Demo"); 
} 
public class Consultation { 
    public int IdUser {get;set;} 
    public DateTime DateCreate {get;set;} 
    public int IdTypeConsult {get;set;} 
} 
public class UsuersViewModel : Consultation { 
    public string Sex {get;set;} 
} 
public class DataBase { 
    public IEnumerable<Consultation> CONSULT { 
     get { 
      return new List<Consultation>{ 
       new Consultation { IdUser = 1, DateCreate=DateTime.Today, IdTypeConsult = 2}, 
       new Consultation { IdUser = 2, DateCreate=DateTime.Today.AddDays(1), IdTypeConsult = 4} 
      }; 
     }} 
    public IEnumerable<UsuersViewModel> USER { 
     get { 
      return new List<UsuersViewModel>{ 
       new UsuersViewModel { IdUser = 1, Sex="M"}, 
       new UsuersViewModel { IdUser = 1, Sex="M"}, 
       new UsuersViewModel { IdUser = 2, Sex="F"}, 
       new UsuersViewModel { IdUser = 2, Sex="F"} 
      }; 
     }} 
} 

The following is the result:

Cuestiones relacionadas