Ilustración de WhereBulkNotContainsFilterList en EF Core mostrando exclusión de elementos de una lista con íconos de base de datos, filtro y validación.

WhereBulkNotContainsFilterList — excluye elementos de tu lista con precisión

En el artículo anterior exploraste WhereBulkContainsFilterList, una función de Entity Framework Extensions para EF Core que compara tu lista externa contra la base de datos y devuelve únicamente los registros que sí existen. Es la opción ideal cuando necesitas identificar qué elementos requieren un BulkUpdate u otro tipo de validación en base a coincidencias reales.

Hoy veremos su complemento natural: WhereBulkNotContainsFilterList. Esta función recorre tu lista y devuelve solo los elementos que no están presentes en la base de datos, convirtiéndolos en candidatos ideales para un BulkInsert. En otras palabras, automatiza la detección de nuevos registros sin necesidad de bucles manuales ni condiciones repetitivas.

Este método resulta especialmente útil cuando trabajas con datos externos (Excel, JSON de una API o un sistema de terceros) y necesitas sincronizarlos con tu base. Al combinarlo con BulkInsert y BulkUpdate, puedes construir un flujo completo y eficiente de inserción y actualización masiva en tus proyectos de EF Core.


🧬 Ejemplo práctico

Veamos un caso sencillo. Imagina que recibes una lista de productos desde una API externa con dos propiedades clave: Nombre y CategoriaId. Necesitas saber cuáles son nuevos para insertarlos y cuáles ya existen para actualizarlos.
Aquí es donde WhereBulkNotContainsFilterList brilla.

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Lista externa simulada
var deserializedProducts = new List<Producto>
{
    new Producto { Nombre = "Teclado mecánico", CategoriaId = 1, Precio = 59.90m },
    new Producto { Nombre = "Mouse inalámbrico", CategoriaId = 1, Precio = 29.90m },
    new Producto { Nombre = "Monitor 24 pulgadas", CategoriaId = 2, Precio = 149.00m }
};

using (var context = new AppDbContext())
{
    // Filtra de la lista solo los que NO existen en la base
    var noExistentes = context.Productos
        .WhereBulkNotContainsFilterList(deserializedProducts, x => new { x.Nombre, x.CategoriaId })
        .ToList();

    // Complemento: los que sí existen
    var existentes = deserializedProducts.Exclude(noExistentes);

    // Operaciones típicas
    context.BulkInsert(noExistentes);   // nuevos
    context.BulkUpdate(existentes);     // existentes
}

⚡ Versión asíncrona (Web/API)

Además de la versión sincrónica, EF Core y Entity Framework Extensions ofrecen una versión asíncrona ideal para aplicaciones Web y APIs. Usa await para no bloquear el hilo de ejecución y aplica Exclude() para derivar de forma simple los elementos existentes, igual que en el ejemplo sincrónico.

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;
// using System.Linq;
// using System.Collections.Generic;

var deserializedProducts = new List<Producto>
{
    new Producto { Nombre = "Teclado mecánico", CategoriaId = 1, Precio = 59.90m },
    new Producto { Nombre = "Mouse inalámbrico", CategoriaId = 1, Precio = 29.90m },
    new Producto { Nombre = "Monitor 24 pulgadas", CategoriaId = 2, Precio = 149.00m }
};

using (var context = new AppDbContext())
{
    // ✅ Opción A: multiclave con lambda (recomendada)
    var noExistentes = await context.Productos
        .WhereBulkNotContainsFilterListAsync(deserializedProducts, x => new { x.Nombre, x.CategoriaId });

    // ✅ Derivar los que sí existen usando Exclude (más simple y claro)
    var existentes = deserializedProducts.Exclude(noExistentes);

    // Operaciones masivas asincrónicas con Entity Framework Extensions
    await context.BulkInsertAsync(noExistentes);  // nuevos
    await context.BulkUpdateAsync(existentes);    // existentes

    // ✅ Opción B: por nombres de propiedad (equivalente)
    var noExistentesPorNombres = await context.Productos
        .WhereBulkNotContainsFilterListAsync(deserializedProducts, "Nombre", "CategoriaId");

    // // (Opcional) Clave por defecto si coincide con la PK:
    // var noExistentesPorPK = await context.Productos
    //     .WhereBulkNotContainsFilterListAsync(deserializedProducts);
}

💻 Ejemplo interactivo en .NET Fiddle

Haz clic en el siguiente enlace para abrir el ejemplo de WhereBulkNotContainsFilterList directamente en tu navegador:
🔗 Ver directamente en .NET Fiddle

También puedes probarlo aquí mismo, editar el código, ejecutarlo y observar el resultado en tiempo real:


😎 Contexto práctico

Cuando trabajas con datos externos (archivos Excel, JSON de una API o un listado de otro sistema), es común que necesites sincronizar esos registros con tu base de datos. Sin embargo, hacerlo manualmente con bucles y Contains() puede volverse lento y propenso a errores. La idea de WhereBulkNotContainsFilterList es simplificar esa lógica y darte un método listo para filtrar tu lista con eficiencia.


🚀 ¿Qué es WhereBulkNotContainsFilterList?

Es una extensión de Entity Framework Extensions que filtra tu lista en memoria devolviendo únicamente los elementos que no existen en la base de datos. Funciona con claves simples o múltiples, y se apoya internamente en operaciones SQL optimizadas. Esto lo convierte en una herramienta ideal para manejar flujos de insert/update sin sobrecargar la memoria ni escribir lógica repetitiva.

  • Diferencia con WhereBulkContainsFilterList: este último devuelve los que sí existen, mientras que WhereBulkNotContainsFilterList devuelve los que no.
  • Diferencia con WhereBulkNotContains: ese método filtra directamente desde la base, mientras que FilterList trabaja sobre tu lista externa.

🔧 Instalación rápida

Para usar WhereBulkNotContainsFilterList necesitas instalar la librería Entity Framework Extensions. Puedes hacerlo desde la CLI de .NET, la consola de NuGet o desde los sitios oficiales de descarga.

// .NET CLI
dotnet add package Z.EntityFramework.Extensions.EFCore

// Package Manager Console
PM> NuGet\Install-Package Z.EntityFramework.Extensions.EFCore

🔗 Descargar desde entityframework-extensions.net
🔗 Paquete oficial en NuGet.org


🔍 Cómo funciona por dentro

La función sigue una lógica clara y optimizada:

  1. Tu lista externa se copia a una tabla temporal en la base de datos.
  2. Se realiza una unión con tu entidad de EF Core.
  3. Se determina cuáles elementos de la lista no tienen coincidencia.
  4. La función devuelve exactamente esos elementos, listos para ser insertados.

🛠️ Patrón de uso

Existen varias formas de aplicar WhereBulkNotContainsFilterList según tus necesidades:

// Usando la clave por defecto (ej. ProductId)
var lista1 = context.Productos.WhereBulkNotContainsFilterList(deserializedProducts);

// Usando varias propiedades con lambda
var lista2 = context.Productos
    .WhereBulkNotContainsFilterList(deserializedProducts, x => new { x.Nombre, x.CategoriaId });

// Usando nombres de propiedades como lista
var lista3 = context.Productos
    .WhereBulkNotContainsFilterList(deserializedProducts, new[] { "Nombre", "CategoriaId" });

❓ Preguntas frecuentes

Algunas dudas comunes cuando comienzas con esta función:

  • ¿Qué devuelve? Elementos de tu lista externa que no existen en la base.
  • ¿Soporta versión asíncrona? Sí, usa WhereBulkNotContainsFilterListAsync en aplicaciones Web/API.
  • ¿Puedo usar claves compuestas? Sí, define varias propiedades en la lambda o pásalas como string[]/List<string>.
  • ¿Cómo obtengo los que sí existen? Usa el complemento Exclude() sobre tu lista original.

⚙️ Compatibilidad y soporte

Antes de implementar WhereBulkNotContainsFilterList conviene conocer en qué escenarios funciona y en cuáles no.
Aquí tienes un resumen claro para evitar dudas:

  • ✅ Funciona con BulkInsert y BulkUpdate.
  • ❌ No aplica con BatchUpdate o BatchDelete (porque trabajan directamente en BD).
  • ✅ Compatible con EF Core 9 (mantén siempre la librería actualizada).

⚠️ Errores comunes

Aunque la función es sencilla de usar, hay ciertos descuidos típicos que pueden causar errores en tu proyecto.
Toma en cuenta estos puntos para asegurarte de que tu implementación sea correcta:

  • No instalar el paquete correcto o olvidar el using Z.EntityFramework.Extensions;.
  • Escribir mal los nombres de las propiedades al trabajar con claves múltiples.
  • Confundirlo con WhereBulkNotContains, que filtra en la BD, no en la lista.
  • Olvidar la versión Async en aplicaciones Web o APIs.

📚 Recursos útiles

Si quieres profundizar más, aquí tienes los enlaces directos a documentación oficial, descargas y ejemplos prácticos que complementarán lo que aprendiste en este artículo:


📀 ¿Qué sigue?

Has dado un paso clave en la optimización de flujos con EF Core: ahora puedes detectar qué registros de tu lista aún no existen en la base de datos y prepararlos para una inserción masiva eficiente. En el próximo artículo exploraremos BulkMerge() – Inserta o actualiza en un solo flujo (sincronización de listas externas).

🔎 Cada nueva técnica que dominas amplía tu caja de herramientas y te acerca a soluciones más limpias, rápidas y escalables en producción.

Hasta el próximo artículo, y que tus consultas siempre sean rápidas y precisas. 🚀

Scroll to Top