1

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

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

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

用户会经常使用此功能。

我打算这样做:

  1. 删除用户的所有记录

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

  3. 使用 aforeach循环整个集合并一一插入记录

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

有没有更好的方法来做到这一点?

4

6 回答 6

3

如果您有一组对象,那么我会:
将其放入事务中 使用表值参数 (TVP)
删除插入 (并对 PK 上的插入进行排序以最大程度地减少碎片)

通过 TVP 插入有点像反向 DataReader
如果您有原始数据正在解析和加载,我会说 bulkcopy
但您声明您有一个集合
这是关于如何将集合与 TVP 一起使用的很好参考

一次简单地插入一行少于 1000 行应该很快。
如果它是一个非常活跃的表并且很难获得写锁,那就会出现问题。
即使使用简单的插入,您也可以打包多达 100 个值 (),()。
但是,如果您正在寻找速度,我仍然会选择 TVP 超过 100。

于 2013-10-19T13:58:03.587 回答
2

您需要做的就是DELETE执行以下操作之前的用户记录INSERT

为什么不将其作为数据库操作执行(在插入用户记录之前运行此代码):

DELETE FROM MyTable WHERE UserId = @UserId

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

如何对 SQL Server 2008 进行非常快速的插入

并行插入单个表的最快方法

于 2013-10-19T13:31:40.133 回答
2

您可以使用像实体框架这样的 ORM,它支持批量更新。

使用实体框架,您可以这样做:

MyEntities dbContext = new MyEntities();
dbContext.Users.Add(new User(){Name="User1"});
dbContext.Users.Add(new User(){Name="User2"});
dbContext.SaveChanges();

使用实体框架删除所有记录:

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
于 2013-10-19T13:33:40.020 回答
1

为什么不更新必要的字段?好吧,如果您担心性能,请使用原始查询而不是使用 Big ORM。并且根据您的需要,我认为在执行删除和插入操作时最好使用事务。

这是我认为对你有用的:

ado-net-sqltransaction-提高性能

于 2013-10-19T13:44:51.207 回答
0

如果许多记录将保持不变或只需要更新,则不需要删除-插入对。您可以将该MERGE语句与表值参数一起使用,以一次在一个效率最高的语句中执行插入、更新和删除。这可能是最快的方法。MERGE进行了很好的优化,可以以最佳方式一次执行所有写入。

我的经验是,这种技术在实践中效果很好。

于 2013-10-19T14:09:40.633 回答
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 类用于执行过程:

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(connection string) 在 web.config 中初始化

于 2013-12-05T14:57:38.880 回答