2010-08-22 31 views
25

Hola, estoy usando linq para entidad en mi aplicación. Necesito conseguir registros distintos en base a un valor de la columna "Nombre"Obtener registros distintos utilizando linq para la entidad

Así que tengo una tabla similar como se puede ver a continuación:

(User) 
ID 
Name 
Country 
DateCreated 

necesito seleccionar todos estos elementos pero únicos basados ​​en Nombre (único). ¿Es posible lograr el uso de linq, de ser así, por favor muéstrame cómo.

var items = (from i in user select new {i.id, i.name, i.country, i.datecreated}).Distinct(); 
+0

Ha implicado que hay varios registros para cada 'Nombre'. Si eso es cierto, entonces la pregunta también debe indicar cómo elegir los otros campos (id, país, datecreated). Por ejemplo, para cada Nombre, ¿desea el registro con la fecha mínima creada? – crokusek

Respuesta

27

El método Distinct() no funciona bien porque no envía el predicado DISTINCT SQL a la base de datos. group utilizar en su lugar: grupo

var distinctResult = from c in result 
      group c by c.Id into uniqueIds 
      select uniqueIds.FirstOrDefault(); 

de LINQ en realidad crea subgrupos de entidades tecleados por la propiedad que indique:

Smith 
    John 
    Mary 
    Ed 
Jones 
    Jerry 
    Bob 
    Sally 

La sintaxis anterior devuelve las llaves, lo que resulta en una lista distinta. Más información aquí:

http://imar.spaanjaars.com/546/using-grouping-instead-of-distinct-in-entity-framework-to-optimize-performance

+0

Olvidé que necesito usar la unión interna a otra mesa. ¿Podrías mostrarme por favor cómo cambiar el código? – Boommer

+3

Distinct() hace de hecho que el SQL incluya el predicado DISTINCT. ¿Por qué crees que no?Por supuesto, solo lo hará si todavía está trabajando con Iqueryables ... pero lo hace. –

+0

Esta respuesta me salvó totalmente: D ¡Gracias, Dave! – programad

8

El LINQ manera puramente que ocurre es agrupar por nombre, seleccione grupos distintos con llave, a continuación, seleccione basa en eso.

from i in user 
group new {i.ID, i.Country, i.DateRecord} by i.Name into byNmGp 
select byNmGp.First(); 

Editar: Entity Framework es, por supuesto, un proveedor de LINQ muy popular, pero no maneja First() bien aquí, aunque el lógicamente equivalente (en este caso) FirstOrDefault() va a funcionar bien. Prefiero First() cuando no estoy forzado a FirstOrDefault() por las limitaciones de EF, porque su significado se ajusta mejor a lo que se busca aquí.

Otra forma es definir una clase de ayuda:

private class MyRecord : IEquatable<MyRecord> 
{ 
    public int ID; 
    public string Name; 
    public string Country; 
    public DateTime DateCreated; 
    public bool Equals(MyRecord other) 
    { 
    return Name.Equals(other.Name); 
    } 
    public override bool Equals(object obj) 
    { 
    return obj is MyRecord && Equals((MyRecord)obj); 
    } 
    public override int GetHashCode() 
    { 
    return Name.GetHashCode(); 
    } 
} 
/*...*/ 
var items = (from i in user select new MyRecord {i.ID, i.Name, i.Country, i.DateRecord}).Distinct(); 

Esto simplemente define distinta manera diferente. El rendimiento diferirá según si el proveedor de la consulta puede interpretar esa definición de igualdad o no. La comodidad variará según si tiene consultas LINQ similares que hacen más o menos lo mismo.

+0

¿cómo puedo lograr seleccionar varias tablas usando join? – Boommer

+0

'i de iSrc une j de jSrc en i.someField es igual a j.someField'. Aunque no es la misma pregunta, puede ser mejor hacer preguntas por separado en lugar de agregar y agregar al mismo. Las personas miran las preguntas basadas en la pregunta, y conocer la respuesta a una no siempre implica conocer la respuesta a otra. –

+0

Me has entendido mal. Estoy preguntando cómo agrupar o simplemente cómo lograr lo mismo que pido, pero usando la unión interna (varias tablas). – Boommer

1

Hola aquí es cómo puede seleccionar registros distintos con unión interna. Espero que ayuda

var distinctrecords = 
(entity.Table.Join(entity.Table2, x => x.Column, y => y.Column, (x, y) => new {x, y}) 
      .Select(@t => new {@t.x.Column2, @t.y.Column3})) 
      .GroupBy(t => t.Column2) 
      .Select(g => g.FirstOrDefault()); 
2

se puede usar algo como esto:

var distinctReports = reports.Select(c => c.CompanyCode) 
          .Distinct() 
          .Select(c => reports.FirstOrDefault(r => r.CompanyCode == c)) 
          .ToList(); 
1

Aquí está otra variación que terminé usando que se basa fuera la respuesta de Svetlana. Muestra un ejemplo de llenar un control GridView con valores únicos. ¡Gracias!

 dataGridView_AnalyzeTestSuites.DataSource = (
      from tr in _db.TestResults 
      where tr.TaskId == taskId 
      select new { TestSuiteName = tr.Test.TestSuite.Name } 
      ).Distinct().ToList(); 
+0

Esta es la respuesta correcta, ya que el OP preguntó acerca de la sintaxis de linq, no de lambda. –

Cuestiones relacionadas