使用Adapter.Update大批量插入数据的问题

CppPower 2010-05-02 04:09:49

我使用Adapter.Update直接把DataTable里的记录插入到数据库里,但如果DataTable里的主键和数据库原来的记录主键重复,就会出错,后面所有的记录都不能插入了,能不能做到:
排除主键重复的记录,其他不重复的记录仍然可以插入到数据库里

/// <summary>
/// 大批量添加数据ds.Tables[0] 表名strTblName(数据库表名称)
/// </summary>
/// <param name="ds"></param>
/// <param name="strTblName"></param>
/// <returns>受影响的行数</returns>
public int BulkInsert(DataTable dt, string strTblName)
{
int affect = 0;
try
{
using (OleDbConnection conn = new OleDbConnection(AccessHelper.ConnectionStringLocalTransaction))
{
OleDbCommand myCommand = new OleDbCommand("select top 1 * from " + strTblName, conn);
OleDbDataAdapter myAdapter = new OleDbDataAdapter(myCommand);
OleDbCommandBuilder myCommandBuilder = new OleDbCommandBuilder(myAdapter);

myAdapter.InsertCommand = myCommandBuilder.GetInsertCommand();

//foreach (DataRow dr in dt.Rows)
//{
// if (dr.RowState != DataRowState.Added)
// dr.SetAdded();
//}

conn.Open();
affect = myAdapter.Update(dt);
}
}
catch
{
return 0;
}

return affect;
}

...全文
536 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
CppPower 2010-05-02
  • 打赏
  • 举报
回复
看来有很多朋友不明白我的意思,我举一个简单的例子说明情况:
表结构:
ID:自动编号
URL:文本型 长度255 主键

我要采集CSDN论坛的帖子保存到数据库,我昨天采集了10000个帖子,今天又继续采集了20000个帖子放在一个DataTable里,现在要把这个DataTable保存到数据库里,DataTable里的20000个URL肯定和昨天采集的10000个URL有重复的,怎么排除掉重复的URL,保存不重复的URL
CppPower 2010-05-02
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 lhblxm 的回复:]

只能说明数据库设计不够好,为什么不用自动编号的那一列做主键,
在编程的时候就出现麻烦,投入使用后可能会破坏数据的完整性.

-------不要使用有意义的主键
-------永远也不要让用户看到主键
[/Quote]
我晕你哦,自动编号有必要设置为主键吗?自动编号本来就不会重复,当然也没有必要设置为主键
另外,我的程序还在开发中,用户还没看到程序界面,当然也不会看到我设置的主键了
lhblxm 2010-05-02
  • 打赏
  • 举报
回复
只能说明数据库设计不够好,为什么不用自动编号的那一列做主键,
在编程的时候就出现麻烦,投入使用后可能会破坏数据的完整性.

-------不要使用有意义的主键
-------永远也不要让用户看到主键
CppPower 2010-05-02
  • 打赏
  • 举报
回复
我的问题应该是很常用到,应该很简单明了的问题啊:
1、我的DataTable的数据并不是从数据库里来,是为了批量插入而且构造的
2、我的表里有一个自动编号字段,但这个字段不是主键,主键是另外一个字段,我在构造DataTable时可以排除主键重复的记录,但adapter.Update时怎么保证DataTable的主键和数据库中的主键不重复呢?
3、难道真的要把数据库的记录先放到另外一个DataTable,然后和批量插入的DataTable做比较?
wanghui0380 2010-05-02
  • 打赏
  • 举报
回复
不太明白你问题的含义,不知道你具体的应用。

按理说,并不会存在你说的情况

因为如果是同一个表,其主键是只读的,新增的id在未update前实际都是-1,rowstate都是added,根本就不会存在主键重复的道理

如果是从不同表过来的数据,实际上只要结构大致相同,我们可以采用dataTable.Merge()的方法合并两表,ado.net合并的依据实际是主键id,主键id相同为后表数据rowstate为modify,主键id不存在的则插入新数据rowstate为added,从这样看也同样不会出现主键重复而且rowstate为added的情况

另外:实际上你只要更新added的数据话,并没有必要去循环,直接 adapter.Update(dt.Select(null, null, System.Data.DataViewRowState.Added));即可
chichenzhe 2010-05-02
  • 打赏
  • 举报
回复
好比
if(a != 0)
{
c = a;
}
好比 substring
判断是必须有的 。 你必须前置判断。
很多东西你必须提前让待处理的数据处于【绝对不可能非法】的状态(逻辑上)。

所以,解决你这个 问题就是前置数据清理了 ...

批量导入是为了提高效率,降低数据库并发压力。 为此,你应该确保数据的正确性。
koukoujiayi 2010-05-02
  • 打赏
  • 举报
回复
用C#代码可能不行,因为是自动添加的!!
不知道用sql的Insert触发器是不是能行,至少是一条一条添加的!!
没搞过!提个思路!

看看楼下怎么说!!
CppPower 2010-05-02
  • 打赏
  • 举报
回复
再顶上去
没人处理过吗
CppPower 2010-05-02
  • 打赏
  • 举报
回复
试过了,2楼的方法不行,因为不是一条一条插入的,问题出在:affect = myAdapter.Update(dt);
cja03 2010-05-02
  • 打赏
  • 举报
回复
DataTable查询出来后,修改数据,行状态是Modify,在执行Update时,不会Insert,而是Update
DataTable中新增在行,在Update时才是Insert

楼主可以从DataRowState入手解决问题。
songfei5201314 2010-05-02
  • 打赏
  • 举报
回复
有项目管理经验的.NET开发的朋友,可以加上限500人的QQ群28720769,一起交流。
CppPower 2010-05-02
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 koukoujiayi 的回复:]

将你try-catch移到foreach中,catch中没语句,试试
C# code
foreach (DataRow dr in dt.Rows)
{
if (dr.RowState != DataRowState.Added)
try
{
dr.SetAdded();
}
catch
{
}
}

……
[/Quote]

这个我也没有试过,但是并不是使用foreach来一条一条插入记录的,是使用myAdapter.Update(dt);来批量增加的,不知道你说的方法行不行,我一会试试
CppPower 2010-05-02
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 computerfox 的回复:]

楼主要散分,还是问问题,不知道你要问什么关键是。
[/Quote]
不好意思,“排除主键重复的记录”之前应该要加上“能不能”
koukoujiayi 2010-05-02
  • 打赏
  • 举报
回复
将你try-catch移到foreach中,catch中没语句,试试
foreach (DataRow dr in dt.Rows)
{
if (dr.RowState != DataRowState.Added)
try
{
dr.SetAdded();
}
catch
{
}
}
捷哥1999 2010-05-02
  • 打赏
  • 举报
回复
楼主要散分,还是问问题,不知道你要问什么关键是。

110,568

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧