【问题标题】:Optimized Insert Process in a database in asp.net c#在asp.net c#中优化数据库中的插入过程
【发布时间】:2011-09-24 16:01:05
【问题描述】:

我正在使用带有 ms-sql server 2008 express 的 asp.net 4 和 Visual Studio 2010。我使用了三种不同的方式将数据插入到数据库表中:

方式一:

    DataSet dsTab = new DataSet("Table1");
    SqlDataAdapter adp = new SqlDataAdapter("Select * from Table1", con);
    adp.Fill(dsTab, "Table1");

    DataRow dr = dsTab.Tables["Table1"].NewRow();
    dr["col1"] = txtBox1.Text;
    dr["col2"] = txtBox5.Text;
    dr["col3"] = User.Identity.Name.ToString();
    dr["col4"] = "text";
    dr["col5"] = DateTime.Now;
    dr["col6"] = txtBox3.Text;
    dr["col7"] = txtBox2.Text;
    dsTab.Tables["Table1"].Rows.Add(dr);

    SqlCommandBuilder projectBuilder = new SqlCommandBuilder(adp);
    DataSet newSet = dsTab.GetChanges(DataRowState.Added);
    adp.Update(newSet, "Table1");

方式二:

SqlDataAdapter AdapterMessage = new SqlDataAdapter();
AdapterMessage.InsertCommand = new SqlCommand();
AdapterMessage.InsertCommand.Connection = con;
AdapterMessage.InsertCommand.CommandText = "insert into Table1(col1,col2,col3,col4,col5,col6,col7) values ('" + txtBox1.Text + "','" + txtBox5.Text + "','" + User.Identity.Name.ToString(); + "','text','" + DateTime.Now + "','" + txtBox3.Text + "','" + txtBox2.Text + "')";
AdapterMessage.InsertCommand.ExecuteNonQuery();
AdapterMessage.Dispose();

方式3:

string query = "insert into Table1(col1,col2,col3,col4,col5,col6,col7) values ('" + txtBox1.Text + "','" + txtBox5.Text + "','" + User.Identity.Name.ToString(); + "','text','" + DateTime.Now + "','" + txtBox3.Text + "','" + txtBox2.Text + "')";
int i;

SqlCommand cmd = new SqlCommand(query);
con.open();
i = cmd.ExecuteNonQuery();
con.close();

这三种方式中哪一种是网站中最优化的使用方式?

【问题讨论】:

  • 取决于数据量(单个或批量)您还应该查看存储过程,因为这是我个人的选择
  • 这三个都不是好的 - #2 和 #3 特别糟糕。您应该检查参数化查询,而不是将您的 SQL 语句连接在一起 - 这是一种不好的做法,并为 SQL 注入攻击打开了大门。
  • 检查以下内容:stackoverflow.com/questions/2149897/… 简而言之,看看 SQL Server Bulk Insert。如果您有大量数据,速度会非常快

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


【解决方案1】:

您展示的唯一不易受到 SQL 注入攻击的示例是 #1。

由于其他两个很容易受到攻击,#1 是您唯一的选择(在您提供的三个中)。回顾您的代码并立即修复 #2 或 #3 的任何示例。如果你不这样做,你的网站就会被黑。

您是否发现尝试过的各种方法之间存在性能问题?如果不是这样,您最好花时间保护您的网站,而不是过度设计您的代码。

看看SqlParameter class。这是向 SQL Server 提交参数化查询的正确方法,并且在正确使用时消除了 SQL 注入攻击的可能性。

也就是说,如果这是我的代码,我不会使用任何这些选项。这是对我来说似乎最好的方法的伪代码:

using (SqlConnection connection = new SqlConnection(
           connectionString))
{
    SqlCommand command = new SqlCommand(queryString, connection);

    //add parameters here

    command.Connection.Open();
    command.ExecuteNonQuery();
}

【讨论】:

  • 参数我用过很多次了。参数可以与 DataAdapter 以及 SqlCommand 对象一起使用。那么您是否建议在 DataAdapter 上使用 SqlCommand 以及参数?
  • 如果您只是插入一条记录,那么可以。您要插入多个吗?
  • 您可能还应该将SqlCommand 放入using(...) { ... } 块中...
  • @Abe 通常一次只有一条记录。在某些情况下,它不止一个。 @marc_s 使用“使用”块有什么好处?
  • @Abe 如果记录超过 1 条,那么数据适配器更可取? Data Adapter 管理 db 连接的打开和关闭,避免并发。那么这里不是更可取吗?
【解决方案2】:

如果您要插入多行,您可以使用SqlBulkCopy 对象。一个简单的例子:

DataTable dt = new DataTable();
SqlConnection oConn = new SqlConnection(); 
SqlBulkCopy sbc = new SqlBulkCopy(oConn);
sbc.DestinationTableName = "dbo.SomeTable";
sbc.WriteToServer(dt);
sbc.Close();

请记住,DataTable 的架构必须是您要插入的数据库表的架构。

【讨论】:

    【解决方案3】:

    方式 #1:数据集不是对象,这是我唯一的抱怨。

    方式#2:SQL 注入的噩梦!!! SQL Injection

    方式 #3:仍然容易受到 SQL 注入的影响

    如何扩展#3:

    • 使用SqlParameters 避免SQL 注入问题。

    • 不要从表单传递值 直接进入查询,直到他们已经 已通过验证。

    还用相关名称命名您的变量,我在下面的示例中这样做了,但我的名字很糟糕,因为我不知道您尝试插入的数据的详细信息。

    public static void InsertRecordBasedOnView(String goodNameForTextBoxOne,  String goodNameForTextBoxTwo, String goodNameForTextBoxFive, String goodNameForTextBoxThree, String userName)
    {
        const string query = "insert into Table1(col1,col2,col3,col4,col5,col6,col7) values (@valueOne, @valueTwo, @valueThree, @valueFour, @valueFive, @valueSix, @valueSeven)";
    
        SqlParameter columnOne = new SqlParameter("@valueOne", SqlDbType.NVarChar);
        SqlParameter columnTwo = new SqlParameter("@valueTwo", SqlDbType.NVarChar);
        SqlParameter columnThree = new SqlParameter("@valueThree", SqlDbType.NVarChar);
        SqlParameter columnFour = new SqlParameter("@valueFour", SqlDbType.NVarChar);
        SqlParameter columnFive = new SqlParameter("@valueFive", SqlDbType.DateTime);
        SqlParameter columnSix = new SqlParameter("@valueSix", SqlDbType.NVarChar);
        SqlParameter columnSeven = new SqlParameter("@valueSeven", SqlDbType.NVarChar);
    
        columnOne.Value = goodNameForTextBoxOne;
        columnTwo.Value = goodNameForTextBoxFive;
        columnThree.Value = userName;
        columnFour.Value = "Text";
        columnFive.Value = DateTime.Now;
        columnSix.Value = goodNameForTextBoxThree;
        columnSeven.Value = goodNameForTextBoxTwo;
    
        SqlCommand cmd = new SqlCommand(query);
        cmd.Parameters.Add(columnOne);
        cmd.Parameters.Add(columnTwo);
        cmd.Parameters.Add(columnThree);
        cmd.Parameters.Add(columnFour);
        cmd.Parameters.Add(columnFive);
        cmd.Parameters.Add(columnSix);
        cmd.Parameters.Add(columnSeven);
    
        using (SqlConnection connection = new SqlConnection(someConnectionString))
        {
            connection.Open();
            cmd.ExecuteNonQuery();
        }
    }
    

    【讨论】:

      【解决方案4】:

      取决于数据量(单个或批量),但我会说 SqlCommand 的开销可能最小。其他 2 个示例创建了基本插入不需要的附加 DataTable 或 DataAdapter。

      我还会查看存储过程(使用 SqlCommand),因为这是我个人的选择

      【讨论】:

        【解决方案5】:

        SQL Server 2008 支持多行插入,如下所示:

        INSERT INTO MyTable (FirstCol, SecondCol)
        VALUES ('First',1),
        ('Second',2),
        ('Third',3),
        ('Fourth',4),
        ('Fifth',5)
        

        这可能会消除一些开销。

        【讨论】:

        • 他的最后两个例子似乎表明他只想一次插入一行。
        • 哦,是的,你是对的。当我读到他使用 DataSet 时,我被迷住了。
        【解决方案6】:

        我认为你可以在数据库中使用视图!或者像这样的 EntityFramework

        实体;

               using (var context = new ADO_NET_Entities())
                    {
        
                        var newDataset = new stuff();
        
                        stuff.row1InDatatable = "Something";
                        stuff.row2InDatable = "Something";
                        stuff.row3InInDatatable = "Something";
        
                        context.stuff.AddObject(newDataset);
                        context.SaveChanges();
                    }
        

        这里有更多; http://msdn.microsoft.com/en-us/library/aa697427(v=vs.80).aspx

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-10
          • 1970-01-01
          • 1970-01-01
          • 2021-01-28
          • 1970-01-01
          • 2014-02-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多