我有一个数据库表,其实体名为' Item'。此外,我的程序中还有一个Item列表。我想根据此列表更新表。也就是说,我想从数据库表中禁用列表中不存在的项,并将剩余的项添加到数据库中。我尝试了一些方法,但它们似乎效率很低。这里有一些我试过的代码:
DbContext db = new DbContext();
List<Item> newItems = ... // contains lots of items
foreach (Item item in db.ItemSet)
{
if (!newItems.Any(x => x.Id== item.Id))
{
item.Enable = false;
}
}
db.SaveChanges();
上面的代码效率低下,导致SQL Server内存使用量扩大太多。
答案 0 :(得分:2)
您可以对数据库执行查询,以仅检索尚未包含任何新项目ID的记录,并仅标记这些记录。
DbContext db = new DbContext();
List<Item> newItems = ... // contains lots of items
foreach (Item item in db.ItemSet.Where(x => !newItems.Contains(x.Id))
{
item.Enable = false;
}
db.SaveChanges();
技术上效率仍然低,因为它不会批量更新,从而导致更新n + 1方案。但是,它比返回每个记录开始并在应用程序的内存中迭代这些记录更有效。
如果你真的想要一些有效的东西,你总是可以使用像Dapper这样的东西在一次通话中更新不包含你的ID的记录。
using Dapper;
using (var c = new SqlConnection(connectionString))
{
c.Open();
c.Execute(string.Format("UPDATE ItemSet SET Enable = 0 WHERE Id NOT IN ({0})",
BuildIds(newItems.Select(x => x.Id).ToList()));
}
public static class SqlHelpers
{
internal static string BuildIds<T>(IReadOnlyList<T> ids)
{
if (ids.Count <= 0)
return "''";
var agsb = new StringBuilder(string.Format("'{0}'", ids[0]));
for (var i = 1; i < ids.Count; i++)
{
agsb.AppendFormat(", '{0}'", ids[i]);
}
return agsb.ToString();
}
}
同样,您也可以编写一个存储过程来为您处理并直接调用它。
答案 1 :(得分:0)
我认为
列表updateEItems = db.ItemSet.Any(x =&gt; newItems.Any(y =&gt; x.Id == y.Id))
是SELECT WHERE Id IN()
的实体框架