I have implemented Specific Pattern following vkhorikov/SpecificationPattern
For example, i have a product table and it has many to many relation with WarehouseProducts table. I need to find all products for a given list of wearhouses. So, this is what i have kind of
public class Products
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public ICollection<WarehouseProduct> Warehouses { get; set; }
}
public class WarehouseProduct
{
[Key]
public int Id { get; set; }
public int WarehouseId { get; set; }
[ForeignKey("ProductId")]
public int ProductId { get; set; }
}
public class WarehouseProductSpecification : Specification<Products>
{
private readonly List<int> _ids;
public WarehouseProductSpecification(IEnumerable<int> warehouseIds)
{
_ids = warehouseIds.ToList();
}
public override Expression<Func<Products, bool>> ToExpression()
{
Expression<Func<WarehouseProduct, bool>> expr =
(w) => _ids.Contains(w.WarehouseId);
return
q => !_ids.Any()
|| (_ids.Any() && q.Warehouses != null && q.Warehouses.Any(expr.Compile()));
}
}
But, when i execute I got the following error
System.NotSupportedException Cannot compare elements of type 'System.Collections.Generic.ICollection`1[[Data.TableObjects.WarehouseProduct, Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'. Only primitive types, enumeration types and entity types are supported.
I am really struggling to create the specification for a ICollection. Is there any way to achieve that? FYI, I am using EF6 to connect to a SQLServer database.
Updated
// To resond to the first comment..
I have use the spec on the repostiory so the following code gets error
var products = _context.Products
.Include("WarehouseProducts")
.Where(warehouseProductSpec.ToExpression())
.ToList();
so the to list gets the error
Update 2
I tried to use the code added by @Evk
if (_ids.Count == 0)
return x => true;
return q => q.Warehouses.Any(w => _ids.Contains(w.WarehouseId));
I got the following error while trying your code
Test [0:10.297] Failed: System.ArgumentException: Property 'System.String WearhouseId' is not defined for type 'Data.TableObjects.Products'
System.ArgumentException
Property 'System.String WearhouseId' is not defined for type 'Data.TableObjects.Products'
at System.Linq.Expressions.Expression.Property(Expression expression, PropertyInfo property)
at System.Linq.Expressions.ExpressionVisitor.VisitArguments(IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression`1 node)
at System.Linq.Expressions.ExpressionVisitor.VisitArguments(IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
at Infrastructure.Expressions.AndSpecification`1.ToExpression() in C:\..\Expressions\AndSpecification