/// <summary>
        /// 检查是否有重复的码
        /// </summary>
        /// <param name="aadt">准备写入数据库的DataTable</param>
        /// <param name="icodesum">码的总个数</param>
        /// <param name="ilength">码的长度</param>
        /// <param name="scode">码的关键字</param>
        /// <returns>经过处理后,无重复码的List链表</returns>
       private List<string> CheckWriteData(DataTable aadt,int icodesum,int ilength,string scode)
        {
            using (SqlConnection conn = new SqlConnection())
            {
                List<string> value = new List<string>(icodesum); 
                SqlCommand cmd = new SqlCommand();
                conn.ConnectionString = ConfigurationManager.ConnectionStrings["fwwlConnectionString"].ConnectionString;
                conn.Open();
                try
                {
                    //首先删除临时表的记录
                    cmd.CommandTimeout = 600;
                    cmd.Connection = conn;
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = "Delete TmpCode";
                    cmd.ExecuteNonQuery();                    //把所生的码写入临时表(可能会有复制的码)
                    using (SqlBulkCopy bcp = new SqlBulkCopy(conn))
                    {
                        bcp.BatchSize = aadt.Rows.Count % 100;
                        bcp.BulkCopyTimeout = 3600;
                        bcp.DestinationTableName = "TmpCode";
                        bcp.WriteToServer(aadt);
                    }                    using (DataTable dt = new DataTable ())
                    {
                        //把重复的码去掉,并补齐个数
                        cmd.CommandTimeout = 3600;
                        cmd.CommandText = "Select DISTINCT code from TmpCode";
                        SqlDataAdapter sdr = new SqlDataAdapter (cmd);
                        sdr.Fill(dt);                        //检查有多少个重复的码,并用循环补足个数
                        if (dt.Rows.Count < icodesum)
                        {
                            int i = icodesum - dt.Rows.Count;
                            for (int m = 0; m < i; m++)
                            {
                                DataRow dr = dt.NewRow();
                                dr["code"] = Code(ilength, scode, m).ToString(); //生成新的码
                                dt.Rows.Add(dr);
                            }
                        }                        //把DataTable中的数据,存入List中,准备返回
                        for (int m = 0; m < dt.Rows.Count; m++)
                        {
                            value.Add(dt.Rows[m]["code"].ToString());
                        }
                        dt.Dispose();
                    }
                    return value;
                }
                catch (Exception ex)
                {
                    FileLog.InsertXml(ex.Message);
                    return value;
                }
            }
        }如量数据量在100万,或150万的时候,速度还可以接受。但超过150万的时候,程序几乎无法运行了。请牛人帮忙解决一下。几天了,实在想不出更好的方法了。
在线等。
小弟先谢了

解决方案 »

  1.   

    方法的参数和返回值需要重新设计一下,百万级的List不现实
    像WindowsAPI,超过一百的对象就会用回调方法或枚举器来枚举了,而不会直接返回一个列表
    就像EmunWindows、FindFirst、FindNext等
      

  2.   

    直接在数据库里做union看看,union操作可以删去重复的内容
      

  3.   

    code  在数据库里是什么类型?有很多地方都可以优化,我给你个按你考虑方式的优化 等我写写
      

  4.   

    用list 返回时,150万的数据,也就六七分钟左右时间,还可以接受。
    大过150万的时候,程序就死了。code  是一个字符串型,dr["code"] = Code(ilength, scode, m).ToString(); //生成新的码这个地方当参数传递使用
      

  5.   

    我也试过,把DataTable中的内容搞进DataView中,然后再利用DataView的ToTable()方法来去掉重复值,这样就可以不用读写数据库了。
    不过这种方法好像更慢样。
      

  6.   

                //using (DataTable dt = new DataTable())
                //{
                    //把重复的码去掉,并补齐个数
                    cmd.CommandTimeout = 3600;
                    cmd.CommandText = "Select DISTINCT code from TmpCode";
                    //SqlDataAdapter sdr = new SqlDataAdapter(cmd);
                    //sdr.Fill(dt);
                    SqlDataReader dr = cmd.EndExecuteReader();
                    while (dr.Read())
                    {
                        value.Add(dr["code"].ToString());
                    }
                    dr.Close();
                    //检查有多少个重复的码,并用循环补足个数
                    if (dt.Rows.Count < icodesum)
                    {
                        int i = icodesum - dt.Rows.Count;
                        for (int m = 0; m < i; m++)
                        {
                            //DataRow dr = dt.NewRow();
                            //dr["code"] = Code(ilength, scode, m).ToString(); //生成新的码
                            //dt.Rows.Add(dr);
                            value.Add(Code(ilength, scode, m).ToString());
                        }
                    }
                    
                    //把DataTable中的数据,存入List中,准备返回
                    //for (int m = 0; m < dt.Rows.Count; m++)
                    //{
                    //    value.Add(dt.Rows[m]["code"].ToString());
                    //}
                    //dt.Dispose();
                //}// 其实去掉重复值的办法有很多,比如用hashTable,只一个字段的类型 怎么写都没所谓了
      

  7.   

    小改了一下,感觉没必要把重复的码先放进datatable中,直接往list中放就可以了
    另外,用hashtable来替换list是不是更好些。        private List<string> CheckWriteData(DataTable aadt, int icodesum, int ilength, string scode)
            {
                using (SqlConnection conn = new SqlConnection())
                {
                    List<string> value = new List<string>();
                    SqlCommand cmd = new SqlCommand();
                    conn.ConnectionString = ConfigurationManager.ConnectionStrings["fwwlConnectionString"].ConnectionString;
                    conn.Open();
                    try
                    {
                        //首先删除临时表的记录
                        cmd.CommandTimeout = 600;
                        cmd.Connection = conn;
                        cmd.CommandType = CommandType.Text;
                        cmd.CommandText = "Delete TmpCode";
                        cmd.ExecuteNonQuery();                    //把所生的码写入临时表(可能会有复制的码)
                        using (SqlBulkCopy bcp = new SqlBulkCopy(conn))
                        {
                            bcp.BatchSize = aadt.Rows.Count % 100;
                            bcp.BulkCopyTimeout = 3600;
                            bcp.DestinationTableName = "TmpCode";
                            bcp.WriteToServer(aadt);
                        }                    using (DataTable dt = new DataTable())
                        {
                            //把重复的码去掉,并补齐个数
                            cmd.CommandTimeout = 3600;
                            cmd.CommandText = "Select DISTINCT code from TmpCode";
                            SqlDataAdapter sdr = new SqlDataAdapter(cmd);
                            sdr.Fill(dt);                        //把DataTable中的数据,存入List中,准备返回
                            for (int m = 0; m < dt.Rows.Count; m++)
                            {
                                value.Add(dt.Rows[m]["code"].ToString());
                                
                            }
                            if (dt.Rows.Count < icodesum) {
                                string newcode = Code(ilength, scode, m).ToString();
                                for (int i = dt.Rows.Count - 1; i < icodesum; i++)
                                {
                                    value.Add(newcode);
                                }
                            }
                            dt.Dispose();
                        }
                        return value;
                    }
                    catch (Exception ex)
                    {
                        FileLog.InsertXml(ex.Message);
                        return value;
                    }
                }
            }
      

  8.   

    还有就是这里用 sqlreader 效率要高很多(cmd.ExecuteReader();……)
    最后 能不写ToString的 就别写,那可是内存啊
      

  9.   

    奉劝你一句,别在这里浪费时间了,如果你取出来的数据非常的大,而且非常多的重复,那么就建议你取重构你的数据表,在C#中,List存储、时延、响应等等的效率是最高的,除非你比微软牛B,自己些一个List,否则就别在这里找出路了,其实是找到也不会高效到那里去,本末倒置了。
      

  10.   

    我就不相信你哪个地方要一次用到这List中所有的数据
    当数据量大时,原则是要用哪些就取哪些你先说说你返回那么大一个List打算干嘛吧
      

  11.   

    多谢各位,最终我觉定在数据库中用一个存储过程来解决这个问题。
    当数量为200万条记录时,用时10分钟左右,但不会死机了。
    CREATE PROCEDURE [dbo].[CheckDataDistinct]
    @tableName nvarchar(30),  --表名
    @sumCount int,  --码的个数
    @ilength_fw int, --防伪码的长度
    @ilength_wl int, --物流码的长度
    @scode nvarchar(10)  --码的关键字
    AS
    declare @strSql nvarchar(300)  --存储准备执行的SQL语句 
    declare @tableCount int
    declare @tmpCode_fw nvarchar(30)  --临时存放新生成的码
    declare @tmpCode_wl nvarchar(30)  --临时存放新生成的码 --从大到小处理物流码
    Create Table  #MyTmpeTable(id int,code_fw nvarchar(30),code_wl nvarchar(30),
                        flag_wl int, select_Sum_Count int)
    Set @strSql = '
    Insert  Into #MyTmpeTable
       Select a.*
          from '+ @tableName + ' a where
            id = (select min(id) from '+@tableName+' where code_wl = a.code_wl) order by a.id'
    exec(@strSql)--去掉物流码的所有重复值
    Select  @tableCount = Count(id) From #MyTmpeTable  --去掉重复值后还剩于的码个数

    while @tableCount < @sumCount  --补齐码的个数
    begin
       Set @tmpCode_fw = dbo.Code(@ilength_fw,@scode,@tableCount)  --生成新码
       Set @tmpCode_wl = dbo.Code(@ilength_wl,@scode,@tableCount)  --生成新码
       Insert into #MyTmpeTable(id,code_fw,code_wl,flag_wl,select_Sum_Count)
         Values(@tableCount,@tmpCode_fw,@tmpCode_wl,0,0)
       Set @tableCount = @tableCount+1
    end

    --从小到大处理防伪码
    Create Table  #MyTable_fw(id int,code_fw nvarchar(30),code_wl nvarchar(30),
                        flag_wl int, select_Sum_Count int)
    Set @strSql = '
    Insert  Into #MyTable_fw
       Select a.*
          from #MyTmpeTable a where
            id = (select min(id) from #MyTmpeTable where code_fw = a.code_fw) order by a.id'
    exec(@strSql)--去掉防伪码的所有重复值
    Select  @tableCount = Count(id) From #MyTable_fw  --去掉重复值后还剩于的码个数
    Set @tableCount = @sumCount - @tableCount
    while @tableCount   > 0   --补齐码的个数
    begin
       Set @tmpCode_fw = dbo.Code(@ilength_fw,@scode,@tableCount)  --生成新码
       Set @tmpCode_wl = dbo.Code(@ilength_wl,@scode,@tableCount)  --生成新码
       Insert into #MyTable_fw(id,code_fw,code_wl,flag_wl,select_Sum_Count)
         Values(@tableCount,@tmpCode_fw,@tmpCode_wl,0,0)
       Set @tableCount = @tableCount - 1
    end

    --把处理后的码,写回原表中

    Set @strSql = 'delete  '+@tableName
    exec(@strSql)

    Set @strSql = 'Insert into '+@tableName+' (code_fw,code_wl,flag_wl,select_Sum_Count '+
                      ') Select code_fw,code_wl,flag_wl,select_Sum_Count From #MyTable_fw '
    exec(@strSql)
    GO
    CREATE FUNCTION [dbo].[Code]  (@ilength int,@scode nvarchar(30),@inum int) 
    RETURNS   nvarchar(50)
    BEGIN 
    --变量
    declare @alength int
    declare @strTmp nvarchar(50)  --新生成的码,返回用set @alength = @ilength - 6  --需要补齐的位数
    Set @strTmp = @inum  --码的关键字if len(@strTmp) > @alength
    begin  
       Set @strTmp = substring(@strTmp,1,@ilength)
    end
    else
    begin
      declare @ailength int
      set @ailength = @alength - len(@strTmp)  --需要循环处理的次数
      declare @j int
      set @j = 0
      
      while @j < @ailength
      begin
        Set @strTmp = '0'+@strTmp
        Set @j = @j+1
      end
      Set @strTmp = @scode + @strTmp
    endRETURN(@strTmp)
    END
      

  12.   

     while @tableCount   > 0   --补齐码的个数
    这个地方的循环插入应该是比较耗时的,我感觉。 可以换个思路,先做整体插入,然后重复的部分采用update的机制来做,可能快一些
      

  13.   

    如果用UPDATE来做的话,代码就要复杂一些了。
    要取出重复的码,
      

  14.   


    楼主如果决定在数据库上优化的话,建议到sql版。
    效率应该能提高不少的。
    针对sql的优化方法就很多了,到了百万级,表变量和临时表已经有区别了。临时表可以加索引,而表变量是不可以加的。