I'm trying to write Linq query on this Products table based on FacetTypes that need to be grouped by their Facet.
This is the table structure:
I get passed an array of facetTypeIds, say 9, 6, 52
FacetTypeId 9 has a name of "160" and is a Facet of "Size"
FacetTypeId 6 has a name of "157" and is a Facet of "Size"
FacetTypeId 52 has a name of "Cool Brand" and is a Facet of "Brand"
They need to be constructed into a query that joins based on the facet, like this:
select * from products p
inner join (select productId from productFacets where facetTypeId in (9, 6))
p1 on p1.productId = p.productId
inner join (select productId from productFacets where facetTypeId in (52))
p2 on p2.productId = p.productId
The outcome is a result set that says:
Get me Products which have brand "Cool Brand" and Sizes of (160 or 157)
How would I go about creating a linq query that will dynamically build this?
I'm kinda stuck as to how this would be formed in linq.
EDIT:
This is 开发者_StackOverflowthe code I've sort of come up with however it feels pretty inefficient.
MyDbContext _context;
// Groups FacetTypeIds by Facet into int lists
Dictionary<int, List<int>> createFacetGroup(int[] facetTypeIds)
{
var facets = new Dictionary<int, List<int>>();
var facetTypes = from ft in _context.FacetTypes where facetTypeIds.Contains(ft.FacetTypeId) select ft;
foreach (var facetType in facetTypes)
{
if (facets.ContainsKey(facetType.Facet.FacetId))
facets[facetType.Facet.FacetId].Add(facetType.FacetTypeId);
else
facets.Add(facetType.Facet.FacetId, new List<int> { facetType.FacetTypeId });
}
return facets;
}
public List<Product> FindProductsByGroupedFacetTypeIds(int[] facetTypeIds)
{
var groupedFacetTypeIds = createFacetGroup(facetTypeIds);
// this seem very inefficient but ToList needs to be called
// otherwise the results products in the foreach loop dont end
// up with the correct result set
var products = _context.Products.ToList();
foreach (var facetTypeIdGroup in groupedFacetTypeIds)
{
var facetTypeIdGroupArray = facetTypeIdGroup.Value.ToArray();
products = (from p in products where p.FacetTypes.Any(x => facetTypeIdGroupArray.Contains(x.FacetTypeId)) select p).ToList();
}
return products;
}
Try this
If your entity model name is YourEntitie
for example :
YourEntitie urEntity = new YourEntitie();
List<Products> prdList = (from pro in urEntity.Products.Include("FacetTypes")
where (pro.FacetTypes.Where
(fac => fac.FacetTypeID == 9 ||
fac => fac.FacetTypeID == 6).Count() > 0)
&& (pro.FacetTypes.Where
(fac => fac.FacetTypeID == 52).Count() > 0)
select pro).ToList();
In the interests of closing this question, i'll submit my solution for this.
It's not pretty but it works. If anyone else has a better solutions, I'd love to see it
MyDbContext _context;
// Groups FacetTypeIds by Facet into int lists
Dictionary<int, List<int>> createFacetGroup(int[] facetTypeIds)
{
var facets = new Dictionary<int, List<int>>();
var facetTypes = from ft in _context.FacetTypes where facetTypeIds.Contains(ft.FacetTypeId) select ft;
foreach (var facetType in facetTypes)
{
if (facets.ContainsKey(facetType.Facet.FacetId))
facets[facetType.Facet.FacetId].Add(facetType.FacetTypeId);
else
facets.Add(facetType.Facet.FacetId, new List<int> { facetType.FacetTypeId });
}
return facets;
}
public List<Product> FindProductsByGroupedFacetTypeIds(int[] facetTypeIds)
{
var groupedFacetTypeIds = createFacetGroup(facetTypeIds);
// this seem very inefficient but ToList needs to be called
// otherwise the results products in the foreach loop dont end
// up with the correct result set
var products = _context.Products.ToList();
foreach (var facetTypeIdGroup in groupedFacetTypeIds)
{
var facetTypeIdGroupArray = facetTypeIdGroup.Value.ToArray();
products = (from p in products where p.FacetTypes.Any(x => facetTypeIdGroupArray.Contains(x.FacetTypeId)) select p).ToList();
}
return products;
}
精彩评论