我有一个表(和Dto)有两个主键:int
和string
类型:
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,所以有些事情是不对的。
我不确定我采取了正确的方法。
答案 0 :(得分:2)
您需要将int
和string
的唯一对传递给该方法。您可以使用元组传递单个列表,而不是传入两个单独的列表:
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引擎兼容。可能是一个开始的好地方。