/// <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万的时候,程序几乎无法运行了。请牛人帮忙解决一下。几天了,实在想不出更好的方法了。
在线等。
小弟先谢了
解决方案 »
- C#调用Oracle里的函数,返回一个结果集。。求代码
- winform,主窗体的工具栏按钮 如何在不同的子窗体中使用
- C++中的char *在函数中作为传出参数 C#中如何进行匹配,才能正确获得字符串的值
- .NET 泛型的问题
- 使用socket编程,自己实现一个web服务器,能够使用IE打开我们服务器上的网页
- 水晶报表11.5版本,如何设置纸张大小?
- 100分求把winform里的内容保存成word文档 或者 直接实现 打印与预览。
- 已经生成了下面的这棵树,但没有赋上x,y的标签,我要把这两个x,y值回写到数据库,用来做菜单的
- 从dll类库向调用者传递异常(的消息),用什么方法?
- c#中命名空间的问题---超低级问题
- 请问各位谁有远程读取较大的MDB文件经验,我在读取的时候总是超时. 急!!!!
- 急救!!!
像WindowsAPI,超过一百的对象就会用回调方法或枚举器来枚举了,而不会直接返回一个列表
就像EmunWindows、FindFirst、FindNext等
大过150万的时候,程序就死了。code 是一个字符串型,dr["code"] = Code(ilength, scode, m).ToString(); //生成新的码这个地方当参数传递使用
不过这种方法好像更慢样。
//{
//把重复的码去掉,并补齐个数
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,只一个字段的类型 怎么写都没所谓了
另外,用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;
}
}
}
最后 能不写ToString的 就别写,那可是内存啊
当数据量大时,原则是要用哪些就取哪些你先说说你返回那么大一个List打算干嘛吧
当数量为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
这个地方的循环插入应该是比较耗时的,我感觉。 可以换个思路,先做整体插入,然后重复的部分采用update的机制来做,可能快一些
要取出重复的码,
楼主如果决定在数据库上优化的话,建议到sql版。
效率应该能提高不少的。
针对sql的优化方法就很多了,到了百万级,表变量和临时表已经有区别了。临时表可以加索引,而表变量是不可以加的。