sintaxis c# linq

c# - sintaxis - ¿Cómo harías una consulta de "no estar" con LINQ?



linq notation c# (15)

elementos en la primera lista donde el correo electrónico no existe en la segunda lista.

from item1 in List1 where !(list2.Any(item2 => item2.Email == item1.Email)) select item1;

Tengo dos colecciones que tienen propiedad de Email en ambas colecciones. Necesito obtener una lista de los elementos en la primera lista donde el Email no existe en la segunda lista. Con SQL solo usaría "not in", pero no sé el equivalente en LINQ. ¿Cómo se hace eso?

Hasta ahora tengo una unión, como ...

var matches = from item1 in list1 join item2 in list2 on item1.Email equals item2.Email select new { Email = list1.Email };

Pero no puedo unirme ya que necesito la diferencia y la unión fallaría. Necesito alguna forma de usar Contains o Exists, creo. Simplemente no he encontrado un ejemplo para hacer eso todavía.


¿No podría hacer una unión externa, solo seleccionando los elementos de la primera lista si el grupo está vacío? Algo como:

Dim result = (From a In list1 Group Join b In list2 On a.Value Equals b.Value Into grp = Group Where Not grp.Any Select a)

No estoy seguro de si esto funcionaría de alguna manera eficiente con el marco de Entidad.



Ejemplo utilizando la lista de int para la simplicidad.

List<int> list1 = new List<int>(); // fill data List<int> list2 = new List<int>(); // fill data var results = from i in list1 where !list2.Contains(i) select i; foreach (var result in results) Console.WriteLine(result.ToString());


En el caso de que uno use el Entity Framework de ADO.NET , la solución de EchoStorm también funciona perfectamente. Pero me tomó unos minutos para envolver mi cabeza alrededor de ella. Suponiendo que tiene un contexto de base de datos, dc, y desea encontrar filas en la tabla x no vinculadas en la tabla y, la respuesta de la respuesta completa se ve así:

var linked = from x in dc.X from y in dc.Y where x.MyProperty == y.MyProperty select x; var notLinked = dc.X.Except(linked);

En respuesta al comentario de Andy, sí, uno puede tener dos de en una consulta LINQ. Aquí hay un ejemplo completo de trabajo, usando listas. Cada clase, Foo y Bar, tiene una identificación. Foo tiene una referencia de "clave externa" a Bar a través de Foo.BarId. El programa selecciona todos los Foo no vinculados a una barra correspondiente.

class Program { static void Main(string[] args) { // Creates some foos List<Foo> fooList = new List<Foo>(); fooList.Add(new Foo { Id = 1, BarId = 11 }); fooList.Add(new Foo { Id = 2, BarId = 12 }); fooList.Add(new Foo { Id = 3, BarId = 13 }); fooList.Add(new Foo { Id = 4, BarId = 14 }); fooList.Add(new Foo { Id = 5, BarId = -1 }); fooList.Add(new Foo { Id = 6, BarId = -1 }); fooList.Add(new Foo { Id = 7, BarId = -1 }); // Create some bars List<Bar> barList = new List<Bar>(); barList.Add(new Bar { Id = 11 }); barList.Add(new Bar { Id = 12 }); barList.Add(new Bar { Id = 13 }); barList.Add(new Bar { Id = 14 }); barList.Add(new Bar { Id = 15 }); barList.Add(new Bar { Id = 16 }); barList.Add(new Bar { Id = 17 }); var linked = from foo in fooList from bar in barList where foo.BarId == bar.Id select foo; var notLinked = fooList.Except(linked); foreach (Foo item in notLinked) { Console.WriteLine( String.Format( "Foo.Id: {0} | Bar.Id: {1}", item.Id, item.BarId)); } Console.WriteLine("Any key to continue..."); Console.ReadKey(); } } class Foo { public int Id { get; set; } public int BarId { get; set; } } class Bar { public int Id { get; set; } }


Gracias, Brett. Tu sugerencia me ayudó también. Tenía una lista de Objetos y quería filtrarla utilizando otra lista de objetos. Gracias de nuevo....

Si alguien necesita, por favor, eche un vistazo a mi ejemplo de código:

''First, get all the items present in the local branch database Dim _AllItems As List(Of LocalItem) = getAllItemsAtBranch(BranchId, RecordState.All) ''Then get the Item Mappings Present for the branch Dim _adpt As New gItem_BranchesTableAdapter Dim dt As New ds_CA_HO.gItem_BranchesDataTable _adpt.FillBranchMappings(dt, BranchId) Dim _MappedItems As List(Of LocalItem) = (From _item As LocalItem In _AllItems Join _ dr As ds_CA_HO.gItem_BranchesRow In dt _ On _item.Id Equals dr.numItemID _ Select _item).ToList _AllItems = _AllItems.Except(_MappedItems.AsEnumerable).ToList Return _AllItems


No LINQ to Entities esto con LINQ to Entities :

NorthwindDataContext dc = new NorthwindDataContext(); dc.Log = Console.Out; var query = from c in dc.Customers where !dc.Orders.Any(o => o.CustomerID == c.CustomerID) select c;

Alternativamente:

NorthwindDataContext dc = new NorthwindDataContext(); dc.Log = Console.Out; var query = from c in dc.Customers where dc.Orders.All(o => o.CustomerID != c.CustomerID) select c; foreach (var c in query) Console.WriteLine( c );


No sé si esto te ayudará, pero ...

NorthwindDataContext dc = new NorthwindDataContext(); dc.Log = Console.Out; var query = from c in dc.Customers where !(from o in dc.Orders select o.CustomerID) .Contains(c.CustomerID) select c; foreach (var c in query) Console.WriteLine( c );

de la cláusula NOT IN en LINQ to SQL por Marco Russo


Para cualquier persona que también quiera usar un operador IN similar a SQL en C #, descargue este paquete:

Mshwf.NiceLinq

Tiene métodos In y NotIn :

var result = list1.In(x => x.Email, list2.Select(z => z.Email));

Incluso puedes usarlo de esta manera.

var result = list1.In(x => x.Email, "[email protected]", "[email protected]", "[email protected]");


Para las personas que comienzan con un grupo de objetos en memoria y realizan consultas en una base de datos, he encontrado que esta es la mejor manera de hacerlo:

var itemIds = inMemoryList.Select(x => x.Id).ToArray(); var otherObjects = context.ItemList.Where(x => !itemIds.Contains(x.Id));

Esto produce una bonita cláusula WHERE ... IN (...) en SQL.


Puede tomar ambas colecciones en dos listas diferentes, digamos list1 y list2.

Entonces solo escribe

list1.RemoveAll(Item => list2.Contains(Item));

Esto funcionará.


Puede usar una combinación de Dónde y Cualquier para encontrar que no está en:

var NotInRecord =list1.Where(p => !list2.Any(p2 => p2.Email == p.Email));


Si bien Except es parte de la respuesta, no es la respuesta completa. Por defecto, Except (como varios de los operadores LINQ) hace una comparación de referencia en los tipos de referencia. Para comparar por valores en los objetos, tendrás que

  • implementa IEquatable<T> en tu tipo, o
  • anular Equals y GetHashCode en su tipo, o
  • pase una instancia de un tipo que implemente IEqualityComparer<T> para su tipo

También se podría usar All()

var notInList = list1.Where(p => list2.All(p2 => p2.Email != p.Email));


var secondEmails = (from item in list2 select new { Email = item.Email } ).ToList(); var matches = from item in list1 where !secondEmails.Contains(item.Email) select new {Email = item.Email};