Búsqueda deseable en lista anidada por lista anidada
Por favor, alguien me puede ayudar debajo de Linq EF Tengo objetos similares
Class Product
{
public string Name { get; set; }
public virtual ICollection ProductAttributes { get; set; }
}
class sc : Product { }
class ProductAttributes
{
public long ProductID { get; set; }
public virtual Product Product { get; set; }
public long AttributesDtlID { get; set; }
}
cuando estoy tratando de buscar en el producto = ProductoAtributos con SC = confianza ProductoAtributos Había creado abajo Queryable
Product.Where(X => X.ProductAttributes.Any(m => sc.ProductAttributes.Any(A => m.AttributesDtlID == A.AttributesDtlID)));
También lo intenté
Product.Where(X => X.ProductAttributes.AsEnumerable().Any(m => sc.ProductAttributes.Any(A => m.AttributesDtlID == A.AttributesDtlID)));
pero tengo el error de abajo
LINQ expression ''DbSet
.Where(p => p.IsDeleted == False)
.Where(p => (MaterializeCollectionNavigation(
navigation: Navigation: Product.ProductAttributes,
subquery: DbSet
.Where(p0 => EF.Property>(p, "ID") != null && EF.Property>(p, "ID") == EF.Property>(p0, "ProductID")))
.AsEnumerable()
.Any(m => __sc_ProductAttributes_0
.Any(A => m.AttributesDtlID == A.AttributesDtlID)))'' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Pregunta hecha hace 3 años, 4 meses, 28 días - Por compilerchieftain
4 Respuestas:
-
class Product { // primary key public long Id { get; set; } // name of product public string Name { get; set; } // relation to attributes public virtual List
ProductAttributes { get; set; } } class ProductAttribute { // primary key public long Id { get; set; } // product link public long ProductID { get; set; } public virtual Product Product { get; set; } // this is the property which you want to test in your query (as far as I have understood) public long AttributesDtlID { get; set; } } Si desea obtener todos los productos ahora que tienen cualquier vínculo con un producto con atributo id '1230' haga lo siguiente:
DbSet
Products; <-- this comes from the Entity Framework long id = 1230; List result; result = Products .Where(p => p.ProductAttributes .Where(attr => attr.AttributesDtlID == id) .Count != 0) .ToList(); Si usted quiere lo mismo para una lista dada de los ids lo hace así:
DbSet
Products; <-- this comes from the Entity Framework List ids = new List (){1230, 100, 20} List result; result = Products .Where(p => p.ProductAttributes .Where(attr => ids.Contains(attr.AttributesDtlID)) .Count != 0) .ToList(); Respondida el Dec 18, 2020 a las 16:50 - por algorithmwizard
Votos positivos: 0 | Votos negativos: 0 -
Tus clases no tienen campos de identificación y no están seguras para qué clase es.
Pero, asumiendo:
Class Product { public long ID { get; set; } <- PK public string Name { get; set; } public virtual ICollection
ProductAttributes { get; set; } } class ProductAttributes { public long ID { get; set; } <- PK public long ProductID { get; set; } public virtual Product Product { get; set; } public long AttributesDtlID { get; set; } } y quieres emular (de nuevo adivinando que la unión debe ser P.ID = A.ProductID):
select * from Product P join ProductAttributes A on P.ID = A.ProductID where A.AttributesDtlID in (1,2,3)
luego utilizar:
List
attrDtlIdsFilter = new List { 1, 2, 3 }; List products = Product.Where(p => ProductAttributes.Where(pa => attrDtlIdsFilter.Contains(pa.AttributesDtlID)) .Select(pa => pa.ProductID) .Contains(p.ID)); UPDATE
Desglose de la consulta:
// Get a List of ProductAttributes where AttrobutesDtlID is in the List // of attributesIds that we want to filter on ProductAttributes.Where(pa => attrDtlIdsFilter.Contains(pa.AttributesDtlID)) // From that List, just 'select' ProductID from each ProductAttribute .Select(pa => pa.ProductID) // Looks to see if Product.ID is that List of ProductIDs .Contains(p.ID)
Respondida el Dec 18, 2020 a las 16:57 - por binarybuilder
Votos positivos: 0 | Votos negativos: 0 -
El error que estás obteniendo se debe a que estás intentando realizar una comparación entre colecciones directamente en la consulta de LINQ, lo cual no es soportado por EF. Para solucionar este problema, puedes llevar a cabo la comparación entre las colecciones después de haber obtenido los datos de la base de datos. Para ello, deberías ajustar tu consulta de la siguiente manera:
csharp var productAttributesIds = sc.ProductAttributes.Select(A => A.AttributesDtlID).ToList(); var result = Product .Where(X => X.ProductAttributes .Any(m => productAttributesIds.Contains(m.AttributesDtlID))) .ToList();
En este código, primero obtienes los IDs de los atributos del producto
sc
y luego los utilizas para verificar si algúnProductAttributes
del productoProduct
tiene un ID que esté contenido en la lista de IDs recién obtenida.Este enfoque debería evitar el error que estás experimentando y te permitirá obtener los resultados deseados.
Respondida el Dec 19, 2020 a las 16:51 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Opción 1: Uso de
AsQueryable()
Modifica tu consulta para incluir
AsQueryable()
antes de llamar aAny()
:C
Product.Where(X => X.Productczuk.AsQueryable().Any(m => sc.Productczuk.Any(A => m.czukDtlID == A.czukDtlID)))
Opción 2: Uso de
ToList()
Convierte las colecciones internas a listas antes de llamar a
Any()
:C
Product.Where(X => X.Productzuk.ToList().Any(m => sc.Productzuk.ToList().Any(A => m.zukDtlID == A.zukDtlID)))
Opción 3: Uso de variables intermedias
Asigna las colecciones internas a variables intermedias y luego usa esas variables en la consulta
Any()
:C
var productczuk = X.Productczuk.ToList();
var scProductczuk = sc.Productczuk.ToList(); Product.Where(X => productczuk.Any(m => scProductczuk.Any(A => m.czukDtlID == A.czukDtlID)))Explicación
El error se produce porque la consulta contiene una subconsulta anidada que intenta evaluar la colección interna
Product zuk
como un conjunto de datos completo. Para evitar esto, debemos asegurarnos de que la colección interna se evalúe como un objeto de consulta enumerable (IQueryable
) o como una lista (List
).Las opciones anteriores logran esto de manera diferente:
AsQueryable()
devuelve un objeto de consulta enumerable que puede ser procesado por el proveedor de datos.ToList()
convierte la colección en una lista que se evalúa localmente. * El uso de variables intermedias permite especificar explícitamente que la colección interna se evalúe localmente.Respondida el Dec 19, 2020 a las 16:57 - por Gemini
Votos positivos: 0 | Votos negativos: 0