lambda表达式中的SQL double'IN'子句

时间:2017-04-19 15:50:11

标签: c# sql .net entity-framework lambda

我有一个表(和Dto)有两个主键:intstring类型:

public class Foo
{
    public int Id { get; set; }
    public string Data { get; set; }

    // other members...
}

所以,我有一个List<Dto> dtoList,我从一个DbContext获得。我需要在其他DbContext中获得相同的dtos。问题是PK是一对两列。

这是我做的方式(似乎它不起作用):

public IEnumerable<FooDto> GetFooByPrimaryKeys(List<int> ids, List<string> data)
{
    return FooContext.Foo.Where(f => ids.Contains(f.Id) && data.Contains(f.Data));
}

但它会返回我需要的更多行。我的意思是,我正在通过1300对并获得1500个dtos,所以有些事情是不对的。

我不确定我采取了正确的方法。

2 个答案:

答案 0 :(得分:2)

您需要将intstring的唯一传递给该方法。您可以使用元组传递单个列表,而不是传入两个单独的列表:

public IEnumerable<FooDto> GetFooByPrimaryKeys(List<Tuple<int, string>> keys)
{
    return FooContext.Foo.Where(f => keys.Any(x => x.Item1 == f.Id && x.Item2 == f.Data));
}

如果实体框架无法处理此问题,您可以选择获取所有记录,然后过滤内存中已实现记录的列表:

public IEnumerable<FooDto> GetFooByPrimaryKeys(List<Tuple<int, string>> keys)
{
    return FooContext.Foo.ToList().Where(f => keys.Any(x => x.Item1 == f.Id && x.Item2 == f.Data));
}

如果您有大量记录,可能需要考虑编写存储过程:

How to pass an array into a SQL Server stored procedure

Passing an array/table to stored procedure through Entity Framework

无论如何,这里的主要问题是您需要与值的进行比较。

答案 1 :(得分:1)

您方法中的参数似乎并不像复合键那样处理复合键。

GetFooByPrimaryKeys(List<Tuple<int, string>> ids){ ... }

它会为您提供您正在寻找的密钥对。

然后.Where(f => ids.Contains(new Tuple<int, string> (f.Id, f.Data)))...

注意:我还没有尝试过此代码,不确定它是否与EF的lambda引擎兼容。可能是一个开始的好地方。