我有一个ASP.NET Web应用程序,我需要一次删除并插入多个记录。
假设用户点击了一个按钮。它将删除该用户的所有现有记录,并将一组新记录插入数据库。
例如,用户A在数据库中有720条记录。当用户单击 Update 按钮时,它将删除现有的700条记录并将一组新记录(假设为854条记录)插入数据库。
用户经常使用此功能。
我打算这样做:
删除用户的所有记录
将所有记录存储在集合
使用foreach
循环遍历整个集合并逐个插入记录
但我担心可能存在性能问题。
有没有更好的方法呢?
答案 0 :(得分:3)
如果你有一个对象的集合,那么我会:
把它放在交易中
删除
使用表值参数(TVP)插入
(并对PK上的插入进行排序以最大限度地减少碎片)
通过TVP插入有点像反向DataReader
如果您有解析和加载的原始数据,我会说批量复制
但是你说你有一个收藏品
This is great reference on how to use a collection with TVP
只需简单地插入一行一行,少于1000就应该非常快 如果它是一个非常活跃的表,并且很难获得写锁定就会出现问题 即使使用简单的插入,您最多可以打包100个值(),() 但是,如果你正在寻找速度,我仍然可以使用TVP购买超过100的东西。
答案 1 :(得分:2)
在执行DELETE
之前,您需要做的只是INSERT
用户记录:
为什么不将此作为数据库操作(在插入用户记录之前运行此代码):
DELETE FROM MyTable WHERE UserId = @UserId
关于插入记录的最快方法,您可以找到很多帖子:
答案 2 :(得分:2)
您可以使用ORM,例如支持批量更新的实体框架。
使用Entity Framework,您可以这样做:
MyEntities dbContext = new MyEntities();
dbContext.Users.Add(new User(){Name="User1"});
dbContext.Users.Add(new User(){Name="User2"});
dbContext.SaveChanges();
使用Entity Framework删除所有记录:
dbContext.Database.ExecuteSqlCommand("delete from User");
您可以在一批中进行所有更改:
//get all or needed users
List<User> users = dbContext.Users.ToList();
foreach (var user in users)
{
if (CheckCondition) //update user
{
user.Name = "new name";
dbContext.Entry(user).State = EntityState.Modified;
}
else if (CheckCondition) // delete user
{
dbContext.Entry(user).State = EntityState.Deleted;
}
}
dbContext.Users.Add(new User() {Name = "Name3"}); //add new user
dbContext.SaveChanges(); //save all changes in one batch in a single transaction
答案 3 :(得分:1)
为什么不更新必要的字段? 好吧,如果您担心性能,请使用原始查询而不是使用Big ORM。根据您的需要判断,我认为在执行删除和插入操作时使用事务会更好。
我认为这对你有用:
答案 4 :(得分:0)
如果许多记录保持不变或只需要更新,则不需要删除 - 插入对。您可以将MERGE
语句与表值参数一起使用,以在一个最大效率语句中一次执行插入,更新和删除。这可能是最快的方式。 MERGE
已经过优化,可以以最佳方式一次执行所有写入。
我的经验是,这种技术在实践中很有效。
答案 5 :(得分:0)
您可以在Datatable中的数据库表中插入批量行。
使用以下我多次使用过:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.ApplicationBlocks.Data;
using System.Data.SqlClient;
using System.Data;
using AssamExitPollReport;
using System.IO;
using System.Drawing;
using Spire.Xls;
using System.Data.Sql;
public partial class Default : System.Web.UI.Page
{
DataSet ds = new DataSet();
clsdata obj = new clsdata();
protected void Page_Load(object sender, EventArgs e)
{
string tablename = Request.QueryString["tablename"];
// Response.ContentType = "text/xml"; //Set Content MIME Type.
Response.Write("<h3>Execution Started on " + DateTime.Now.ToLocalTime()+"</h3>");
bool flg=false;
if (tablename != null)
{
flg = BulkInsertDataTable(tablename);
if (flg)
Response.Write("<br><h3>Successfully executed on " + DateTime.Now.ToLocalTime() + "</h3>");
else
Response.Write("<br><h3>Oops! Something is wrong.</h3>");
}
else
Response.Write("<br><h3>Oops! @parameter \"tablename\" is missing.</h3>");
}
//public bool BulkInsertDataTable(string tableName, DataTable dataTable)
public bool BulkInsertDataTable(string tablename)
{
bool isSuccuss=true;
try
{
string client = "Server=databasehost\\SQLEXPRESS;Database=dbname;Uid=username;Pwd=yourpassword;Trusted_Connection=no";
ds = obj.Executedatasetcount("select_tablename");
obj.ExecuteDataset("delete_temp", new object[] { tablename });
using (SqlConnection destinationConnection = new SqlConnection(client))
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(destinationConnection))
{
destinationConnection.Open();
bulkCopy.DestinationTableName = tablename;
bulkCopy.WriteToServer(ds.Tables[0]);
destinationConnection.Close();
}
}
catch (Exception ex)
{
isSuccuss = false;
}
return isSuccuss;
}
private void elseif(bool p)
{
throw new NotImplementedException();
}
}
clsdata clase用于执行程序:
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Microsoft.ApplicationBlocks.Data;
namespace AssamExitPollReport
{
public class clsdata
{
// string conn = "Data Source=ADMIN-B19C3BADF;Initial Catalog=bazarkhodro;Integrated Security=True";
public DataSet Executedataset(string spName)
{
return SqlHelper.ExecuteDataset(System.Configuration.ConfigurationManager.ConnectionStrings["conn1"].ConnectionString, CommandType.StoredProcedure, spName);
}
public DataSet ExecuteDataset(string spName, object[] values)
{
return SqlHelper.ExecuteDataset(System.Configuration.ConfigurationManager.ConnectionStrings["conn1"].ConnectionString, spName, values);
}
public DataSet ExecuteDataset(string spName, object[] values, string conn)
{
return SqlHelper.ExecuteDataset(conn, spName, values);
}
public int ExecuteNonQuery(string spName, object[] values, string conn)
{
int i = 0;
try
{
i = SqlHelper.ExecuteNonQuery(conn, spName, values);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return i;
}
public int ExecuteScaler(string spName, object[] values)
{
int i = 0;
try
{
i = Convert.ToInt32(SqlHelper.ExecuteScalar(System.Configuration.ConfigurationManager.ConnectionStrings["conn"].ConnectionString, spName, values));
}
catch (Exception)
{
throw;
}
return i;
}
public int ExecuteScaler(string spName, object[] values, string conn)
{
int i = 0;
try
{
i = Convert.ToInt32(SqlHelper.ExecuteScalar(conn, spName, values));
}
catch (Exception)
{
throw;
}
return i;
}
}
}
其中conn(连接字符串)在web.config中初始化