【问题标题】:Quick insert from C# CLR从 C# CLR 快速插入
【发布时间】:2013-05-16 10:47:34
【问题描述】:

我正在处理大量数据,并使用 CLR 进行处理。 CLR 处理工作很快,但我需要一种快速的方法将处理后的数据移动到数据库中(通过 CLR)。

例如看下面的clr代码

protected static string Normalize(string s) // space and special character remover
    {
        char[] arr = s.ToCharArray();
        arr = Array.FindAll<char>(arr, (c => char.IsLetterOrDigit(c)));
        return new string(arr).ToLower();
    }

    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void udpNormStr ()
    {
        SqlConnection con = new SqlConnection("context connection = true");
        SqlCommand cmd = new SqlCommand("Select cName from NamesTable", con);
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        DataTable dt = new DataTable();
        DataTable fill = new DataTable();
        fill.Columns.Add("NormName", typeof(string));
        da.Fill(dt);
        cmd.CommandText = "insert into NormTable values (@nName)";
        cmd.Parameters.Add("@nName", SqlDbType.VarChar);
        foreach (DataRow row in dt.Rows)
        {
            fill.Rows.Add(Normalize(row[0].ToString()));
        }
        con.Open();
        foreach (DataRow row in fill.Rows)
        {
            cmd.Parameters["@nName"].Value = row[0];            
            cmd.ExecuteNonQuery();            
        }
        con.Close();
}

执行需要花费大量时间,并且在插入操作中浪费了 90% 的时间。 请提出一种将处理后的数据移动到数据库的更好方法(通过 CLR)。

【问题讨论】:

标签: c# sql sql-server clr bulkinsert


【解决方案1】:

SqlBulkCopy;既然你已经有一个DataTable,你可以使用:

using (var bcp = new SqlBulkCopy(con))
{
    bcp.DestinationTableName = "NormTable";
    bcp.WriteToServer(dt);
}

请注意,对于流式传输数据,您还可以创建自定义IDataReader 实现并将其提供给WriteToServer

【讨论】:

  • 正如我已经提到的,我正在使用 CLR,并且 Bulk Copy 无法在 Context Connections 中工作。收到错误,如此处所述sqlclr.net/Articles/tabid/54/articleType/ArticleView/articleId/…
  • @PranayLasod "CLR"本质上是“.NET”的另一种说法; SqlBulkCopy 在 .NET 中工作得很好。我怀疑你的意思是你正在使用 SQL/CLR,即 CLR inside SQL Server。这在您的问题中显而易见,是的,这会改变事情。但要明确的是,说“CLR”和“SQL-Server”没有明确表示 SQL/CLR 是:对数据库的非常标准的 .NET 框架数据访问。请编辑您的问题以明确您正在使用 SQL/CLR;谢谢。
【解决方案2】:

使用 SqlTransaction 包装您的连接以避免隐式事务。

con = new SqlConnection("context connection=true");
con.Open();
using (con)
{
    using (var sqlTrans = con.BeginTransaction()) //one transaction instead of many from each insert implicit
    {
        const string cmdText = @"INSERT INTO [table1] ([a],[b],[c],[d],[e]) VALUES (@a,@b,@c,@d,@e)";
        using (var cmd = new SqlCommand(cmdText, con, sqlTrans))
        {
            var aField = cmd.Parameters.Add("@a", SqlDbType.NVarChar, 255);
            var bField = cmd.Parameters.Add("@b", SqlDbType.Int);
            var cField = cmd.Parameters.Add("@c", SqlDbType.Bit);
            var dField = cmd.Parameters.Add("@d", SqlDbType.NVarChar, 255);
            var eField = cmd.Parameters.Add("@e", SqlDbType.Int);

            //same for all
            cField.Value = false;
            dField.Value = "d";
            eField.Value = 1;

            foreach (var someValue in valueCollection)
            {
                aField.Value = someValue.Key; 
                bField.Value = someValue.Value; 
                cmd.ExecuteNonQuery();
            }
        }
        sqlTrans.Commit();
    }
    con.Close();
}

【讨论】:

    【解决方案3】:

    如果这项工作是 SQL/CLR,那么这很棘手。一种想法可能是使该方法仅返回数据,例如作为CLR Table-Valued Function,然后在TSQL 中从表值函数中提取INSERT

    【讨论】:

    • 好的,这是我迄今为止找到的唯一方法,而且由于我也在建议中得到了这种方法,我相信我应该只继续使用这种方法。感谢您的帮助。
    【解决方案4】:

    尝试使用 SQLBulkCopy

    这是一次性将数据表插入数据库的示例方法

     public static bool SaveDetails(DataTable dbTable)
        {
            try
            {
                SqlConnection conn = new SqlConnection("Data Source=akshay;Initial Catalog=CosmosDB;User Id=sa;Password=Nttdata123");
                conn.Open();
                SqlBulkCopy sbc = new SqlBulkCopy(conn);
    
    
                if (dbTable.Rows.Count > 0)
                {
                    sbc.DestinationTableName = "Employee";
                    sbc.WriteToServer(dbTable);              
    
    
                }
    
                sbc.Close();
                conn.Close();
    
    
                return true;
    
    
    
            }
            catch (Exception exp)
            {
    
                return false;
            }
    
        }
    

    【讨论】:

    • 正如我已经提到的,我正在使用 CLR,并且 Bulk Copy 无法在 Context Connections 中工作。收到错误,如此处所述sqlclr.net/Articles/tabid/54/articleType/ArticleView/articleId/…
    • @PranayLasod "CLR"本质上是“.NET”的另一种说法; SqlBulkCopy 在 .NET 中工作得很好。我怀疑你的意思是你正在使用 SQL/CLR,即 CLR inside SQL Server。这在您的问题中显而易见,是的,这会改变事情。但要明确的是,说“CLR”和“SQL-Server”没有明确表示 SQL/CLR 是:对数据库的非常标准的 .NET 框架数据访问。请编辑您的问题以明确说明您正在使用 SQL/CLR。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-16
    • 1970-01-01
    相关资源
    最近更新 更多