TheCodeJunkie
TheCodeJunkie

Reputation: 9616

Fetching items which has a specific set of child elements (advanced query - possible?)

I have a SQL database (SQL Server 2008) which contains the following design

ITEM

META

There exists a N-N relationship between these two, i.e an Item can contain zero or more meta references and a meta can be associated with more than one item. Each meta can only be assocated with the same item once. This means I have the classic table in the middle

ITEMMETA

I would like to to execute a LinqToSql query to extract all of the item entities which contains a specific set of meta links. For example, give me all the Items which have the following meta items associated with it

Is it possible to write such a query with the help of LinqToSql? Let me provide some more requirements

I hope its clear what I'm trying to achieve, I feel Im not being quite as clear as I'd hoped =/ Let's hope its enough :)

Thank you!

Upvotes: 2

Views: 145

Answers (3)

Lucas
Lucas

Reputation: 17434

This should work for you:

string[] criteria = new[] { "Car", "Ford", "Offroad" };

var items = 
    from i in db.Item
    let wantedMetas = db.Meta.Where(m => criteria.Contains(m.Name))
    let metas = i.ItemMeta.Select(im => im.Meta)
    where wantedMetas.All(m => metas.Contains(m))
    select i;

Basically it compares the "wanted" metas against each item's metas, and selects the items which have all the wanted metas (or more).

Upvotes: 2

Amy B
Amy B

Reputation: 110161

You could filter the items by counting the filtered metas.

List<string> metaList = new List<string>() { "Car", "Ford", "Offroad" };
int metaListCount = metaList.Count;
List<Item> result =
  db.Items
  .Where(i => metaListCount ==
    i.ItemMeta.Meta
    .Where(m => metaList.Contains(m.Name))
    .Count()
  )
  .ToList();

Be aware that there is an upper limit for this in-memory collection .Contains imposed by SqlServer's parameter limit (it's either ~200 or ~2000, I can never remember).

Upvotes: 1

Andrew Theken
Andrew Theken

Reputation: 3480

this brings back anything that matchs any of the meta criteria, and then filters it down to only things that match all the criteria. (also, keep in mind that you'll need to have your relationship defined in your datacontext). Let us know if you need clarification.

var db = new YourDataContext();
var possibleItems = (from m in db.Metas where <meta criteria> select m.ItemMetas.Item);

var items = possibleItems.GroupBy(y=>y).Where(x=>x.Count() == criteriaCount).Select(x=>x.Key);

Upvotes: 1

Related Questions