如何使用 linq to sql 一次更新多行?
Posted
技术标签:
【中文标题】如何使用 linq to sql 一次更新多行?【英文标题】:how to update the multiple rows at a time using linq to sql? 【发布时间】:2012-04-25 11:19:30 【问题描述】:表:
id userid friendid name status
1 1 2 venkat false
2 1 3 sai true
3 1 4 arun false
4 1 5 arjun false
如果用户发送userid=1,friendids=2,4,5 status=true
我将如何编写查询来更新上述内容?所有friendids
状态均为真。 [一次 2,3,4 个]?
【问题讨论】:
【参考方案1】:要更新一列,这里有一些语法选项:
选项 1
var ls=new int[]2,3,4;
using (var db=new SomeDatabaseContext())
var some= db.SomeTable.Where(x=>ls.Contains(x.friendid)).ToList();
some.ForEach(a=>a.status=true);
db.SubmitChanges();
选项 2
using (var db=new SomeDatabaseContext())
db.SomeTable
.Where(x=>ls.Contains(x.friendid))
.ToList()
.ForEach(a=>a.status=true);
db.SubmitChanges();
选项 3
using (var db=new SomeDatabaseContext())
foreach (var some in db.SomeTable.Where(x=>ls.Contains(x.friendid)).ToList())
some.status=true;
db.SubmitChanges();
更新
根据评论中的要求,展示如何更新多个列可能是有意义的。因此,假设出于本练习的目的,我们不仅要更新status
at 个。我们要更新name
和status
匹配的friendid
。以下是一些语法选项:
选项 1
var ls=new int[]2,3,4;
var name="Foo";
using (var db=new SomeDatabaseContext())
var some= db.SomeTable.Where(x=>ls.Contains(x.friendid)).ToList();
some.ForEach(a=>
a.status=true;
a.name=name;
);
db.SubmitChanges();
选项 2
using (var db=new SomeDatabaseContext())
db.SomeTable
.Where(x=>ls.Contains(x.friendid))
.ToList()
.ForEach(a=>
a.status=true;
a.name=name;
);
db.SubmitChanges();
选项 3
using (var db=new SomeDatabaseContext())
foreach (var some in db.SomeTable.Where(x=>ls.Contains(x.friendid)).ToList())
some.status=true;
some.name=name;
db.SubmitChanges();
更新 2
在我使用 LINQ to SQL 的答案中,在这种情况下提交到数据库的用法是:
db.SubmitChanges();
但要让实体框架提交更改:
db.SaveChanges()
【讨论】:
对于多个 cmets 你需要做:records.ForEach(x=> x.Deleted = true; x.DeletedByUserID = deletedByUserId; x.DeletedOn = DateTime.Now; );
不应该是db.SaveChanges()
而不是db.SubmitChanges()
吗?
...您的所有三个选项都是相同的。事实上,前两者之间的唯一区别是一个使用变量而一个不使用。两者兼有只会增加噪音。
注意:这将生成一个单独的 SQL 更新查询 per 行。在这种情况下它不是,但如果 # 行是“重要的”(即 mil 的、k 的甚至 100 的),您可能希望通过嵌入式 SQL 或存储过程来使用单个 SQL 更新查询。来源:“social.msdn.microsoft.com/Forums/en-US/…”
可以不用ToList()
吗?这是一个杀手【参考方案2】:
不要在接受的答案中使用ToList()
方法!
运行 SQL 分析器,我验证并发现 ToList()
函数从数据库中获取所有记录。性能真的很差!!
我会通过纯 sql 命令运行此查询,如下所示:
string query = "Update YourTable Set ... Where ...";
context.Database.ExecuteSqlCommandAsync(query, new SqlParameter("@ColumnY", value1), new SqlParameter("@ColumnZ", value2));
这将在不选择一行的情况下一次性操作更新。
【讨论】:
虽然我同意你的观点,但这个问题确实特别要求 linq 方式。而且,您实际上不需要使用.ToList()
。我相信你可以使用.ForEachAsync()
方法或foreach
没有.ToList()
的常规循环。仍然可能不是很好的表现。但是,如果您非常关心 IMO 的性能,则不应使用 EF。【参考方案3】:
这就是我所做的:
EF:
using (var context = new SomeDBContext())
foreach (var item in model.ShopItems) // ShopItems is a posted list with values
var feature = context.Shop
.Where(h => h.ShopID == 123 && h.Type == item.Type).ToList();
feature.ForEach(a => a.SortOrder = item.SortOrder);
context.SaveChanges();
希望能帮助别人。
注意: 5 年后,正如 cmets 中所说,它不是一个好的选择,因为我正在调用数据库以获取 foreach
中的一些数据。如果你不这样做,那么它可以使用。
【讨论】:
像魅力一样工作! 这很糟糕,你每次都调用数据库来获取记录feature
,而且你不应该在foreach
中添加context.SaveChanges()
,它应该在foreach循环之外。
SQL和EF代码不一样。在 SQL 中,它只是在所有行上运行并更新表的 1 个命令。 EF 代码首先获取所有行,更新 DB 上更改的行,这意味着如果您有 1000 条更新的行,它将执行 1000 条 sql 更新
@stom 还是不一样 :) context.SaveChanges();只需提交您的更新。仍然会有 1000 个更新命令,每个命令都使用 id 而不是 SortOrder 条件
@stom ExecuteSqlCommand 为此存在于 EF 上,但我同意它并不漂亮 :) 无论如何,我的意思是你已经编写了一个 SQL 命令和一个不同的 EF-C# 代码并声称他们是平等的。 :)以上是关于如何使用 linq to sql 一次更新多行?的主要内容,如果未能解决你的问题,请参考以下文章
LINQ to SQL / LINQ to Collections 性能