3

私のコードでは、ユーザーは電話の連絡先リストを含むExcelドキュメントをアップロードできます。開発者はそのExcelファイルを読んでdataTableに変換し、データベースに挿入する必要があります。問題は、一部のクライアントが 5000 以上の連絡先など、大量の連絡先を持っていることです。この量のデータをデータベースに挿入しようとすると、クラッシュしてタイムアウト例外が発生します。この種の例外を回避する最善の方法は何でしょうか?また、ユーザーが長く待たないように挿入ステートメントの時間を短縮できるコードはありますか?

コード

public SqlConnection connection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
public void Insert(string InsertQuery)
{
    SqlDataAdapter adp = new SqlDataAdapter();
    adp.InsertCommand = new SqlCommand(InsertQuery, connection);
    if (connection.State == System.Data.ConnectionState.Closed)
    {
        connection.Open();
    }
    adp.InsertCommand.ExecuteNonQuery();
    connection.Close();
}

protected void submit_Click(object sender, EventArgs e) 
{
    string UploadFolder = "Savedfiles/";
    if (Upload.HasFile) {
        string fileName = Upload.PostedFile.FileName;
        string path=Server.MapPath(UploadFolder+fileName);
        Upload.SaveAs(path);
        Msg.Text = "successfully uploaded";
        DataTable ValuesDt = new DataTable();
        ValuesDt = ConvertExcelFileToDataTable(path);
        Session["valuesdt"] = ValuesDt;
        Excel_grd.DataSource = ValuesDt;
        Excel_grd.DataBind();


    }
}

protected void SendToServer_Click(object sender, EventArgs e)
{
    DataTable Values = Session["valuesdt"] as DataTable ;
    if(Values.Rows.Count>0)
    {
        DataTable dv = Values.DefaultView.ToTable(true, "Mobile1", "Mobile2", "Tel", "Category");
        double Mobile1,Mobile2,Tel;string Category="";
        for (int i = 0; i < Values.Rows.Count; i++)
       {
            Mobile1 =Values.Rows[i]["Mobile1"].ToString()==""?0: double.Parse(Values.Rows[i]["Mobile1"].ToString());
            Mobile2 = Values.Rows[i]["Mobile2"].ToString() == "" ? 0 : double.Parse(Values.Rows[i]["Mobile2"].ToString());
            Tel = Values.Rows[i]["Tel"].ToString() == "" ? 0 : double.Parse(Values.Rows[i]["Tel"].ToString());

           Category = Values.Rows[i]["Category"].ToString();
           Insert("INSERT INTO client(Mobile1,Mobile2,Tel,Category) VALUES(" + Mobile1 + "," + Mobile2 + "," + Tel + ",'" + Category + "')");
           Msg.Text = "Submitied successfully to the server ";
       }



    }

}
4

4 に答える 4

4

SqlBulkCopyDatatable をデータベース テーブルに挿入してみることができます

このようなもの、

using (SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConnection, SqlBulkCopyOptions.KeepIdentity))
{
    bulkCopy.DestinationTableName = DestTableName;
    string[] DtColumnName = YourDataTableColumns;
    foreach (string dbcol in DbColumnName)//To map Column of Datatable to that of DataBase tabele
    {
        foreach (string dtcol in DtColumnName)
        {
            if (dbcol.ToLower() == dtcol.ToLower())
            {
                SqlBulkCopyColumnMapping mapID = new SqlBulkCopyColumnMapping(dtcol, dbcol);
                bulkCopy.ColumnMappings.Add(mapID);
                break;
            }
        }
    }
    bulkCopy.WriteToServer(YourDataTableName.CreateDataReader());
    bulkCopy.Close();
}

詳細については、http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspxを参照してください。

于 2013-06-03T06:40:31.383 に答える
1

一度に 1 行を挿入しているため、この量のデータには非常にコストがかかります

そのような場合は、一括挿入を使用する必要があるため、ロールバックが必要な場合、DB へのラウンド トリップは 1 回だけになります。すべて同じトランザクションです。

于 2013-06-03T06:38:44.223 に答える
0

より多くの作業が必要な SqlBulkCopy を使用するか、SqlAdpater のバッチ更新機能を使用できます。独自の挿入ステートメントを作成してから sqladapter を作成し、それを手動で実行する代わりに、データセットを作成して入力し、1 つの sqldataadpater を作成して、バッチでの挿入数を設定してから、アダプターを 1 回実行します。

コードを繰り返すこともできますが、この記事ではその方法を正確に示しています

protected void SendToServer_Click(object sender, EventArgs e)
{
    DataTable Values = Session["valuesdt"] as DataTable ;
    if(Values.Rows.Count>0)
    {
        DataTable dv = Values.DefaultView.ToTable(true, "Mobile1", "Mobile2", "Tel", "Category");
        //Fix up default values
        for (int i = 0; i < Values.Rows.Count; i++)
       {
            Values.Rows[i]["Mobile1"] =Values.Rows[i]["Mobile1"].ToString()==""?0: double.Parse(Values.Rows[i]["Mobile1"].ToString());
            Values.Rows[i]["Mobile2"] = Values.Rows[i]["Mobile2"].ToString() == "" ? 0 : double.Parse(Values.Rows[i]["Mobile2"].ToString());
            Values.Rows[i]["Tel"] = Values.Rows[i]["Tel"].ToString() == "" ? 0 : double.Parse(Values.Rows[i]["Tel"].ToString());

           Values.Rows[i]["Category"] = Values.Rows[i]["Category"].ToString();
       }
       BatchUpdate(dv,1000);


    }

}
public static void BatchUpdate(DataTable dataTable,Int32 batchSize)
{
    // Assumes GetConnectionString() returns a valid connection string.
    string connectionString = GetConnectionString();

    // Connect to the database.
    using (SqlConnection connection = new SqlConnection(connectionString))
    {

        // Create a SqlDataAdapter.
        SqlDataAdapter adapter = new SqlDataAdapter();

        // Set the INSERT command and parameter.
        adapter.InsertCommand = new SqlCommand(
            "INSERT INTO client(Mobile1,Mobile2,Tel,Category) VALUES(@Mobile1,@Mobile2,@Tel,@Category);", connection);
        adapter.InsertCommand.Parameters.Add("@Mobile1", 
          SqlDbType.Float);
        adapter.InsertCommand.Parameters.Add("@Mobile2", 
          SqlDbType.Float);
        adapter.InsertCommand.Parameters.Add("@Tel", 
          SqlDbType.Float);
        adapter.InsertCommand.Parameters.Add("@Category", 
          SqlDbType.NVarchar, 50);
        adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;

        // Set the batch size.
        adapter.UpdateBatchSize = batchSize;

        // Execute the update.
        adapter.Update(dataTable);
    }
}
于 2013-06-03T06:50:02.540 に答える