[英]Entity Framework Core Read & Update Multiple rows - Composite Primary Key
I have a table structure like this: 我有一个这样的表结构:
ID Code Value
1 2 text1
2 3 text3
2 4 text4
Here ID and Code form the composite primary key ie in the above table you cannot have another row with ID = 2 and Code = 4. 这里的ID和代码构成了复合主键,即,在上表中,您不能有ID = 2和Code = 4的另一行。
Now we are using entity framework core and I have a class called Branch (representing the composite key) and that looks like this: 现在,我们使用实体框架核心,并且我有一个名为Branch(代表复合键)的类,它看起来像这样:
public class Branch
{
public int ID {get; set;}
public int Code {get; set;}
}
Secondly I have a List<Branch>
as well. 其次,我还有一个
List<Branch>
。 Now I want to do two things: 现在我想做两件事:
First make one database call and get the full object (ID, Code, Value) for the entire list of Branch. 首先进行一个数据库调用,并获取整个Branch列表的完整对象(ID,代码,值)。
After that, I will change the 'Value' for each object. 之后,我将更改每个对象的“值”。
Then I want to make one database call and save the updated 'Value' for each row. 然后,我要进行一个数据库调用,并为每一行保存更新的“值”。
Currently I am doing this in a loop so it's inefficient. 目前,我正在循环执行此操作,因此效率低下。
foreach(var x in listOfBranch)
{
var record = context.Table.Find(x.ID, x.Code);
record.Value = "new value";
context.SaveChanges();
}
How can we do this in one call? 我们如何在一个电话中做到这一点? Thanks.
谢谢。
Now I want to do two things:
现在我想做两件事:
First make one database call and get the full object (ID, Code, Value) for the entire list of Branch.
首先进行一个数据库调用,并获取整个Branch列表的完整对象(ID,代码,值)。
After that, I will change the 'Value' for each object.
之后,我将更改每个对象的“值”。
Then I want to make one database call and save the updated 'Value' for each row.
然后,我要进行一个数据库调用,并为每一行保存更新的“值”。
The second part is easy - just move SaveChanges()
call outside of the loop. 第二部分很简单-只需将
SaveChanges()
调用移出循环即可。
The first part is tricky. 第一部分很棘手。 At the time of writing (EF Core 2.0.2),
Contains
can be used only with single property, and joins to in memory collections, Concat
based queries, or filters like 在撰写本文时(EF Core 2.0.2),
Contains
只能与单个属性一起使用,并且可以加入内存集合,基于Concat
的查询或类似的过滤器中
.Where(e => listOfBranch.Any(b => b.ID == e.ID && b.Code == e.Code))
all these are not translated to SQL and are evaluated locally. 所有这些都不会转换为SQL,而是在本地进行评估。
The only way to get the desired result with a single database query is to build dynamically a filter criteria like this: 通过单个数据库查询获得所需结果的唯一方法是动态构建如下过滤条件:
.Where(e =>
(e.ID == listOfBranch[0].ID && e.Code == listOfBranch[0].Code)
||
(e.ID == listOfBranch[1].ID && e.Code == listOfBranch[1].Code)
// ...
||
(e.ID == listOfBranch[N-1].ID && e.Code == listOfBranch[N-1].Code)
)
You can build the above predicate using Expression
class methods as follows (just replace Record
with the type of entity): 您可以按以下方式使用
Expression
类方法构建上述谓词(只需将Record
替换为实体类型):
var parameter = Expression.Parameter(typeof(Record));
var body = listOfBranch
.Select(b => Expression.AndAlso(
Expression.Equal(Expression.Property(parameter, "ID"), Expression.Constant(b.ID)),
Expression.Equal(Expression.Property(parameter, "Code"), Expression.Constant(b.Code))))
.Aggregate(Expression.OrElse);
var predicate = Expression.Lambda<Func<Record, bool>>(body, parameter);
and the usage: 和用法:
foreach (var record in context.Table.Where(predicate))
{
record.Value = "new value";
}
context.SaveChanges();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.