我需要根据要更改的记录列表来更新多个记录。当该列表由一列标识时,这样做很简单:
var fooIds = new List<int> { 2, 3, 4}
var foosToChange = Foo.Where(f => fooIds.Contains(f.Id));
// Update foosToChange and save here
当传入列表是一个具有两个属性以标识记录的对象时,会发生什么?例如:
var fooIds = new []
{
new { prop1 = "12345", prop2 = 2017111701 },
new { prop1 = "hij", prop2 = 2018060101 }
};
这将变成什么?
var foosToChange = Foo.Where(f => fooIds.Contains(???));
这有可能吗?
答案 0 :(得分:1)
下面的查询将完成工作。如果查询必须具有高性能,则可以考虑使用带有Table Valued Parameter的存储过程。
var keys = fooIds.Select(f => f.prop1 + "." + f.prop2);
Foo.Where(f => keys.Contains(f.prop1 + "." + f.prop2))
答案 1 :(得分:0)
应该是这样的:
var foosToChange = Foo.Where(f => fooIds.Any(x => x.prop1 == f.Id1 && x.prop2 == f.Id2));
示例:
A[] Foo = new A[]{ new A{ Id1 = "12345", Id2 = "2017111701" }, new A { Id1 = "fakeid", Id2 = "2017111701" } };
var res = Foo.Where(f => fooIds.Any(x => x.prop1 == f.Id1 && x.prop2 == f.Id2));
// res will return first element
答案 2 :(得分:0)
注意:这可行,但是效率很低。离开此答案是因为它“有效”,但希望较新的答案更好。
这是LinqPad的工作代码:
void Main()
{
var fooToChange = new List<FooClass>
{
new FooClass { CompanyId = "12345", ProcessId = 2017111701 },
new FooClass { CompanyId = "hij", ProcessId = 2018060101 }
};
var foos =
from foo in fooToChange
join fooDb in Foo on
new { CompanyId = foo.CompanyId, ProcessId = foo.ProcessId }
equals
new { CompanyId = fooDb.CompanyId, ProcessId = fooDb.ProcessId }
select fooDb;
foreach(var foo in foos)
{
foo.Status = "Sent";
}
SubmitChanges();
}
public class FooClass
{
public string CompanyId { get; set; }
public int ProcessId { get; set; }
}
答案 3 :(得分:0)
我希望这是最终答案。它行之有效,唯一的低效率是它会选择比原来多的几行,但我愿意忍受。
LinqPad代码:
void Main()
{
var payrolls = new List<PayrollKey>
{
new PayrollKey { CompanyId = "12345", ProcessId = 2017111701 },
new PayrollKey { CompanyId = "hij", ProcessId = 2018060101 }
};
// Store just the companyIds from the incoming list
var companyIds = payrolls.Select(x => x.CompanyId);
// From the DB, get all the foos for the companies in the list.
// We will be getting rows for all processIds for a company, but that's ok because:
// A) I'm guessing that's not super common, and B) they'll be filtered-out in the next query.
var allFoosForCompanies =
from foo in Foo
where foo.Status == "Open" && companyIds.Contains(foo.CompanyId)
select foo;
// Now, from the two in-memory lists, get only the foos we care about
// (having the correct processId).
var foosToChange =
from payroll in payrolls
join foo in allFoosForCompanies on
new { CompanyId = payroll.CompanyId, ProcessId = payroll.ProcessId }
equals
new { CompanyId = foo.CompanyId, ProcessId = foo.ProcessId }
where foo.Status == "Open"
select foo;
// Now make the change and save.
foreach(var foo in foosToChange)
{
foo.Status = "Sent";
}
SubmitChanges();
}
public class PayrollKey
{
public string CompanyId { get; set; }
public int ProcessId { get; set; }
}