从 .net c# 应用程序循环正确有效地更新 sql 服务器数据库 table 中的数百条记录
Properly and efficiently update hundreds of records in sql server db table from .net c# application loop
我已经使用 Entity Framework 6 一段时间了,通常我一次更新 1 条记录。
但是,我需要遍历所有用户,300 - 1,000 个用户
更新数据库中的几个列会不会非常低效和缓慢?与 EF6.x ?我应该改用 ADO.NET 还是通过网络发送某种对象,一些批量更新??
目前我是这样更新的
rpmuser.usr_id = user;
rpmuser = db.rpm_usr.Find(rpmuser.usr_id);
rpmuser.lst_pwd_chg_dtm = dateTime;
rpmuser.cre_dtm = dateTime;
rpmuser.usr_pwd = hash;
rpmuser.salt = salt;
db.SaveChanges();
所以基本上如果我绕过其他用户就可以了吗?我还能如何通过批量更新来做到这一点?
for( .... ) {
// different user id
// all the other needed poco model changes above... etc.
// db.SaveChanges()
}
您可以使用以下代码进行测试:
static void Main(string[] args)
{
CreateAndSeedTheDatabase(); // Step 1: run this
//UpdateAllOfTheProducts(); // Step 2: Comment out the above line and uncomment and run this line
}
static void CreateAndSeedTheDatabase()
{
Context context = new Context();
context.Database.Initialize(true);
Product product;
for (int i = 0; i < 1000; i++)
{
product = new Product() { ProductId = i, Name = "Product" + i };
context.Products.Add(product);
}
context.SaveChanges();
}
static void UpdateAllOfTheProducts()
{
Context context = new Context();
Product[] products = context.Products.ToArray();
foreach (Product product in products)
{
product.Name = product.ProductId + "Product";
}
context.SaveChanges();
}
public class Context : DbContext
{
public Context()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context>());
}
public DbSet<Product> Products { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
}
}
要正确有效地更新数百条记录,您需要尽可能减少数据库往返。
在你的例子中,你有两种方法进行繁重的数据库往返
查找方法
对于您需要更新的每个用户,您都在进行一次数据库往返。有多种方法可以快速减少这种情况。
加载所有用户并使用带有键 "usr_id" 的字典只进行一次数据库往返(如果数据库不包含数百万用户,效果很好!)
创建包含所有 "usr_id" 的列表并使用包含方法
一次检索所有用户
示例:
// Work well if the database doesn't contain to much users
var userDict = db.rpm_usr.ToList().ToDictionary(x => x.usr_id);
// Be careful, the list cannot contains more than 2099 items (SQL Parameters limit = 2100)
var userDict = db.rpm_usr.Where(x => ids.Contains(x.usr_id)).ToDictionary(x => x.usr_id);
两种解决方案都只进行一次数据库往返,可以非常高效地从字典中检索用户。
保存更改方法
SaveChanges 方法为每条要更新的记录执行数据库往返。因此,如果您更新 1000 个用户,将进行 1000 次数据库往返,这非常慢。
免责声明:我是项目的所有者Entity Framework Extensions
此项目允许执行 BulkSaveChanges 和 BulkUpdate 以显着提高性能:
for( .... ) {
// different user id
// all the other needed poco model changes above... etc.
db.BulkSaveChanges()
}
for( .... ) {
// different user id
// all the other needed poco model changes above... etc.
db.BulkUpdate(users)
}
我已经使用 Entity Framework 6 一段时间了,通常我一次更新 1 条记录。
但是,我需要遍历所有用户,300 - 1,000 个用户
更新数据库中的几个列会不会非常低效和缓慢?与 EF6.x ?我应该改用 ADO.NET 还是通过网络发送某种对象,一些批量更新??
目前我是这样更新的
rpmuser.usr_id = user;
rpmuser = db.rpm_usr.Find(rpmuser.usr_id);
rpmuser.lst_pwd_chg_dtm = dateTime;
rpmuser.cre_dtm = dateTime;
rpmuser.usr_pwd = hash;
rpmuser.salt = salt;
db.SaveChanges();
所以基本上如果我绕过其他用户就可以了吗?我还能如何通过批量更新来做到这一点?
for( .... ) {
// different user id
// all the other needed poco model changes above... etc.
// db.SaveChanges()
}
您可以使用以下代码进行测试:
static void Main(string[] args)
{
CreateAndSeedTheDatabase(); // Step 1: run this
//UpdateAllOfTheProducts(); // Step 2: Comment out the above line and uncomment and run this line
}
static void CreateAndSeedTheDatabase()
{
Context context = new Context();
context.Database.Initialize(true);
Product product;
for (int i = 0; i < 1000; i++)
{
product = new Product() { ProductId = i, Name = "Product" + i };
context.Products.Add(product);
}
context.SaveChanges();
}
static void UpdateAllOfTheProducts()
{
Context context = new Context();
Product[] products = context.Products.ToArray();
foreach (Product product in products)
{
product.Name = product.ProductId + "Product";
}
context.SaveChanges();
}
public class Context : DbContext
{
public Context()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context>());
}
public DbSet<Product> Products { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
}
}
要正确有效地更新数百条记录,您需要尽可能减少数据库往返。
在你的例子中,你有两种方法进行繁重的数据库往返
查找方法
对于您需要更新的每个用户,您都在进行一次数据库往返。有多种方法可以快速减少这种情况。
加载所有用户并使用带有键 "usr_id" 的字典只进行一次数据库往返(如果数据库不包含数百万用户,效果很好!)
创建包含所有 "usr_id" 的列表并使用包含方法
一次检索所有用户
示例:
// Work well if the database doesn't contain to much users
var userDict = db.rpm_usr.ToList().ToDictionary(x => x.usr_id);
// Be careful, the list cannot contains more than 2099 items (SQL Parameters limit = 2100)
var userDict = db.rpm_usr.Where(x => ids.Contains(x.usr_id)).ToDictionary(x => x.usr_id);
两种解决方案都只进行一次数据库往返,可以非常高效地从字典中检索用户。
保存更改方法
SaveChanges 方法为每条要更新的记录执行数据库往返。因此,如果您更新 1000 个用户,将进行 1000 次数据库往返,这非常慢。
免责声明:我是项目的所有者Entity Framework Extensions
此项目允许执行 BulkSaveChanges 和 BulkUpdate 以显着提高性能:
for( .... ) {
// different user id
// all the other needed poco model changes above... etc.
db.BulkSaveChanges()
}
for( .... ) {
// different user id
// all the other needed poco model changes above... etc.
db.BulkUpdate(users)
}