C# csv使用c导入无重复项的sqlserver#

C# csv使用c导入无重复项的sqlserver#,c#,sql-server,csv,C#,Sql Server,Csv,我有一个将csv文件导入sql server数据库的小程序 但当你按两次按钮或其他什么东西时,它会添加重复项。 我需要它,这样当有重复的时候,它就会跳过那个。 如果有人能帮我写代码,那就太棒了 编辑:我注意到有人说我需要在按钮工作时禁用该按钮,而这是一个解决方案,我还希望,如果数据库中已经有某个内容,当该部分在csv文件中与数据库中相同时,它将跳过该部分 代码: 将数据批量加载到数据库表时,我遵循的一般原则是创建一个新的暂存表(该表仅在导入期间暂时存在),将所有数据批量加载到该表中,然后运行查询

我有一个将csv文件导入sql server数据库的小程序 但当你按两次按钮或其他什么东西时,它会添加重复项。 我需要它,这样当有重复的时候,它就会跳过那个。 如果有人能帮我写代码,那就太棒了

编辑:我注意到有人说我需要在按钮工作时禁用该按钮,而这是一个解决方案,我还希望,如果数据库中已经有某个内容,当该部分在csv文件中与数据库中相同时,它将跳过该部分

代码:


将数据批量加载到数据库表时,我遵循的一般原则是创建一个新的暂存表(该表仅在导入期间暂时存在),将所有数据批量加载到该表中,然后运行查询将该数据迁移到最终目标表中。之后,只需放下暂存表

这有几个好处:

  • 您可以在不影响使用目标表(例如TableLock)的其他进程的情况下,将其放入数据库/减少初始争用
  • 然后,您可以在第二个迁移步骤中实现一些事情,例如不复制最终目标表中已经存在的数据(如您所希望的那样)

  • 在将数据批量加载到数据库表中时,我遵循的一般原则是创建一个新的暂存表(该表仅在导入期间临时存在),将所有数据批量加载到该表中,然后运行查询将该数据迁移到最终的目标表中。之后,只需放下暂存表

    这有几个好处:

  • 您可以在不影响使用目标表(例如TableLock)的其他进程的情况下,将其放入数据库/减少初始争用
  • 然后,您可以在第二个迁移步骤中实现一些事情,例如不复制最终目标表中已经存在的数据(如您所希望的那样)

  • 来自@AdaTheDev的答案是正确的。但还有另一种方法可以做到这一点

    如果在执行大容量导入时出现重复插入的问题,则也可以使用存储过程而不是使用大容量复制功能来处理该问题

    在2005年以后版本的SQL Server中,您可以使用“表值参数”,也就是说,您可以将整个表作为参数传递到存储过程中,并在服务器端对其进行操作

    如果通过存储过程参数将表传递到服务器端,则可以使用“合并命令”,其中Merge命令是upsert命令。i、 e.您可以以最安全、最快捷的方式从同一命令中插入、更新或删除所需的记录

    以下是有关该过程的一些详细信息:

    步骤1:在SQL Server中创建为表值参数;命令是:

    CREATE TYPE [dbo].[TableTypeName] AS TABLE(
        [ColumnName1] [DataType],
        [ColumnName2] [DataType],
        [ColumnName3] [DataType]
    )
    GO
    
    这里“ColumnName1,2,3”是表列的名称,“DataType”是为列分配的sql server数据类型

    步骤2:使用Merge命令创建存储过程,如下所示:

    CREATE PROCEDURE [dbo].[ProcedureName]
    
        @TableTypeName [dbo].[TableTypeName] READONLY
    
    AS 
    BEGIN
    
        DECLARE @InsertedRowsId TABLE 
        (
            [InsertedRowId] [DataType] NOT NULL
        );
        DELETE FROM @InsertedRowsId;
    
        BEGIN TRY
    
            BEGIN TRANSACTION 
    
                -- Merge command 
                MERGE INTO [dbo].[TableName] AS [Target]
                USING (     
                        SELECT * FROM @TableTypeName                            
                    ) AS [Source]
                -- Candidate Keys: All the column(s) combination that makes the record(s) unique.
                ON [Target].[ColumnName1] = [Source].[ColumnName1] -- Always false, ensures all rows copied
                AND [Target].[ColumnName2] = [Source].[ColumnName2] 
                AND [Target].[ColumnName2] = [Source].[ColumnName2] 
    
                WHEN NOT MATCHED THEN   
                    INSERT 
                        (
                            [ColumnName1]
                            ,[ColumnName1]
                            ,[ColumnName1]
                        )
                    VALUES
                        (
                            [Source].[ColumnName1]
                            ,[Source].[ColumnName1]
                            ,[Source].[ColumnName1]
                        );          
    
            COMMIT TRANSACTION
    
        END TRY
        BEGIN CATCH
            ROLLBACK TRANSACTION
        END CATCH
    
    END 
    
    步骤3:现在是调用存储过程的最后一步

    Private void button1_Click(object sender, EventArgs e)
    {
        string connectionString = @"server=localhost;Initial Catalog=klantbestand;Integrated Security=SSPI;";
        string filepath = @"C:\clients TEST.csv";
    
        StreamReader sr = new StreamReader(filepath);
    
        string line = sr.ReadLine();
        string[] value = line.Split(';');
        DataTable dt = new DataTable();
        DataRow row;
    
        foreach (string dc in value)
        {
            dt.Columns.Add(new DataColumn(dc));
        }
    
        while (!sr.EndOfStream)
        {
            value = sr.ReadLine().Split(';');
            if (value.Length == dt.Columns.Count)
            {
                row = dt.NewRow();
                row.ItemArray = value;
                dt.Rows.Add(row);
            }
        }
    
        if (dt.Rows.Count>0) {
            using (SqlConnection connection = new SqlConnection(connectionString)) {
            connection.Open();
            using (SqlCommand command = connection.CreateCommand()) {
                    command.CommandText = "dbo.ProcedureName";
                    command.CommandType = CommandType.StoredProcedure;
    
                    SqlParameter parameter;            
                    parameter = command.Parameters.AddWithValue("@TableTypeName", dt);              
                    parameter.SqlDbType = SqlDbType.Structured;
                    parameter.TypeName = "dbo.TableTypeName";
    
                    command.ExecuteNonQuery();
                }
            }
        }        
    }
    
    通过这种方式,您可以批量导入数据,而无需任何重复记录。
    甚至,如果需要,您可以记录插入或异常详细信息。

    来自@AdaTheDev的答案是正确的。但还有另一种方法可以做到这一点

    如果在执行大容量导入时出现重复插入的问题,则也可以使用存储过程而不是使用大容量复制功能来处理该问题

    在2005年以后版本的SQL Server中,您可以使用“表值参数”,也就是说,您可以将整个表作为参数传递到存储过程中,并在服务器端对其进行操作

    如果通过存储过程参数将表传递到服务器端,则可以使用“合并命令”,其中Merge命令是upsert命令。i、 e.您可以以最安全、最快捷的方式从同一命令中插入、更新或删除所需的记录

    以下是有关该过程的一些详细信息:

    步骤1:在SQL Server中创建为表值参数;命令是:

    CREATE TYPE [dbo].[TableTypeName] AS TABLE(
        [ColumnName1] [DataType],
        [ColumnName2] [DataType],
        [ColumnName3] [DataType]
    )
    GO
    
    这里“ColumnName1,2,3”是表列的名称,“DataType”是为列分配的sql server数据类型

    步骤2:使用Merge命令创建存储过程,如下所示:

    CREATE PROCEDURE [dbo].[ProcedureName]
    
        @TableTypeName [dbo].[TableTypeName] READONLY
    
    AS 
    BEGIN
    
        DECLARE @InsertedRowsId TABLE 
        (
            [InsertedRowId] [DataType] NOT NULL
        );
        DELETE FROM @InsertedRowsId;
    
        BEGIN TRY
    
            BEGIN TRANSACTION 
    
                -- Merge command 
                MERGE INTO [dbo].[TableName] AS [Target]
                USING (     
                        SELECT * FROM @TableTypeName                            
                    ) AS [Source]
                -- Candidate Keys: All the column(s) combination that makes the record(s) unique.
                ON [Target].[ColumnName1] = [Source].[ColumnName1] -- Always false, ensures all rows copied
                AND [Target].[ColumnName2] = [Source].[ColumnName2] 
                AND [Target].[ColumnName2] = [Source].[ColumnName2] 
    
                WHEN NOT MATCHED THEN   
                    INSERT 
                        (
                            [ColumnName1]
                            ,[ColumnName1]
                            ,[ColumnName1]
                        )
                    VALUES
                        (
                            [Source].[ColumnName1]
                            ,[Source].[ColumnName1]
                            ,[Source].[ColumnName1]
                        );          
    
            COMMIT TRANSACTION
    
        END TRY
        BEGIN CATCH
            ROLLBACK TRANSACTION
        END CATCH
    
    END 
    
    步骤3:现在是调用存储过程的最后一步

    Private void button1_Click(object sender, EventArgs e)
    {
        string connectionString = @"server=localhost;Initial Catalog=klantbestand;Integrated Security=SSPI;";
        string filepath = @"C:\clients TEST.csv";
    
        StreamReader sr = new StreamReader(filepath);
    
        string line = sr.ReadLine();
        string[] value = line.Split(';');
        DataTable dt = new DataTable();
        DataRow row;
    
        foreach (string dc in value)
        {
            dt.Columns.Add(new DataColumn(dc));
        }
    
        while (!sr.EndOfStream)
        {
            value = sr.ReadLine().Split(';');
            if (value.Length == dt.Columns.Count)
            {
                row = dt.NewRow();
                row.ItemArray = value;
                dt.Rows.Add(row);
            }
        }
    
        if (dt.Rows.Count>0) {
            using (SqlConnection connection = new SqlConnection(connectionString)) {
            connection.Open();
            using (SqlCommand command = connection.CreateCommand()) {
                    command.CommandText = "dbo.ProcedureName";
                    command.CommandType = CommandType.StoredProcedure;
    
                    SqlParameter parameter;            
                    parameter = command.Parameters.AddWithValue("@TableTypeName", dt);              
                    parameter.SqlDbType = SqlDbType.Structured;
                    parameter.TypeName = "dbo.TableTypeName";
    
                    command.ExecuteNonQuery();
                }
            }
        }        
    }
    
    通过这种方式,您可以批量导入数据,而无需任何重复记录。
    甚至,如果需要,您也可以记录插入或异常详细信息。

    在按钮工作时创建某种互斥或禁用按钮不是更安全的选择吗?当然,不仅仅是按下两次按钮。当数据库中已经有一个与csv文件中相同的值时,这不是一个更安全的选择吗?在按钮工作时,创建某种互斥或禁用按钮不是更安全的选择吗?这不仅仅是当您按下按钮两次时。当数据库中已经有一个与csv文件中相同的值时,您能帮我编写一些代码吗。我对编程还不是很熟悉。你能帮我写一些代码吗。我对编程还不是很熟悉。所以我尝试了这个,得到了一个例外:System.Data.SqlClient.SqlException类型的未处理异常发生在System.Data.dll中。其他信息:字符串或二进制数据将被截断。表值参数“@TableTypeName”的数据与该参数的表类型不一致。SQL Server错误为:8152,状态:10该语句已终止。异常类型为字符串截断,即为varchar字段定义的大小不够。其次,对于“@TableTypeName”不符合参数的表类型,则“引用存储的Pro中定义的参数名”