如何快速删除然后将多个记录插入数据库

时间:2013-10-19 13:26:33

标签: c# asp.net sql-server-2008

我有一个ASP.NET Web应用程序,我需要一次删除并插入多个记录。

假设用户点击了一个按钮。它将删除该用户的所有现有记录,并将一组新记录插入数据库。

例如,用户A在数据库中有720条记录。当用户单击 Update 按钮时,它将删除现有的700条记录并将一组新记录(假设为854条记录)插入数据库。

用户经常使用此功能。

我打算这样做:

  1. 删除用户的所有记录

  2. 将所有记录存储在集合

  3. 使用foreach循环遍历整个集合并逐个插入记录

  4. 但我担心可能存在性能问题。

    有没有更好的方法呢?

6 个答案:

答案 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

关于插入记录的最快方法,您可以找到很多帖子:

How to do very fast inserts to SQL Server 2008

Fastest way to insert in parallel to a single table

答案 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。根据您的需要判断,我认为在执行删除和插入操作时使用事务会更好。

我认为这对你有用:

ado-net-sqltransaction-improves-performance

答案 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中初始化