简体   繁体   中英

Entity Framework - Join to a List

I need to retrieve a list of entities from my database that matches a list of items in a plain list (not EF). Is this possible with Entity Framework 4.1?

Example:

var list = new List<string> { "abc", "def", "ghi" };
var items = from i in context.Items
            where list.Contains(i.Name)
            select i;

This works great to return rows that match one property, but I actually have a more complex property:

var list = new List<Tuple<string, string>>
{
    new Tuple<string,string>("abc", "123"),
    new Tuple<string,string>("def", "456")
};

// i need to write a query something like this:
var items = from i in context.Items
where list.Contains(new Tuple<string,string>(i.Name, i.Type))
select i;

I know that is not valid because it will say it needs to be a primitive type, but is there any way to do what I'm trying to accomplish or will I need to resort to a stored procedure?

You need to break it down to sub-properties. For example, something like (this might not compile, i'm not able to test at the moment, but it should give you something to work with):

var items = from i in context.Items 
where list.Select(x => x.Item1).Contains(i.Name) 
   && list.Select(x => x.Item2).Contains(i.Type)
select i; 

You have a few options:

1) You could, of course, write a stored procedure to do what you need and call it.

2) You could read the table into memory and then query the in memory list...that way you don't have to use primitives:

var items = from i in context.Items.ToList()
            where list.Contains(new Tuple<string, string>(i.Name, i.Type))
            select i;

3) You could also convert your query to use primitives to achieve the same goal:

 
 
 
 
  
  
  var items = from i in context.Items join l in list on new { i.Name, i.Type } equals new { Name = l.Item1, Type = l.Item2 } select i;
 
 
  

I would go with the second option as long as the table isn't extremely large. Otherwise, go with the first.

You have to think about what the resulting SQL would look like, this would be difficult to do directly in SQL.

My suggestion would be you split out one field of the tuples and use this to cut down the results list, get back the query result then filter again to match one of the tuples eg

var list = new List<string> { "abc", "def" };
var list2 = new List<Tuple<string, string>>
{
  new Tuple<string,string>("abc", "123"),
  new Tuple<string,string>("def", "456")
};
var items = (from i in context.Items
        where list.Contains(i.Name)
        select i)
        .AsEnumerable()
        .Where(i => list2.Any(j => j.val1 == i.Name && j.val2 == i.Type);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM