C# 在linq sql中插入具有唯一索引的多个记录表时发生SqlException
我有一个sql表,其中有一个PK列C# 在linq sql中插入具有唯一索引的多个记录表时发生SqlException,c#,linq-to-sql,unique-index,C#,Linq To Sql,Unique Index,我有一个sql表,其中有一个PK列ItemID,列Value上有唯一索引 CREATE TABLE [dbo].[Item]( [ItemID] [int] IDENTITY(1,1) NOT NULL, [Value] [int] NULL ) CREATE UNIQUE NONCLUSTERED INDEX [IDX_Item_Value_U_NC] ON [dbo].[Item] ( [Value] ASC ) 我正在使用linq sql在表中插入多条记录(批
ItemID
,列Value
上有唯一索引
CREATE TABLE [dbo].[Item](
[ItemID] [int] IDENTITY(1,1) NOT NULL,
[Value] [int] NULL
)
CREATE UNIQUE NONCLUSTERED INDEX [IDX_Item_Value_U_NC] ON [dbo].[Item]
(
[Value] ASC
)
我正在使用linq sql在表中插入多条记录(批插入/更新)。在插入记录之前,我会进行“存在”检查
void MultipleInserts(List<int> values)
{
using (var db = new DBDataContext())
{
foreach (var value in values)
{
var dbItem = db.Items
.Where(x => x.Value == value)
.SingleOrDefault();
if (dbItem == null)
{
var Item = new Item()
{
Value = value
};
db.Items.InsertOnSubmit(Item);
}
}
db.SubmitChanges();
}
}
异常消息:
无法在具有唯一索引“IDX\U Item\U Value\U\U NC”的对象“dbo.Item”中插入重复的键行。声明已终止 我如何避免这种情况 编辑:我无法执行单个插入,因此无法在for循环中移动
db.SubmitChanges()
调用
EDIT2:到目前为止,发布的答案涉及修复数据,而不是LINQSQL中的一种方法。我举了一个简单的例子,其中有一个int列表。但实际上,我有一个要插入的对象图列表,每个项目都会命中多个表进行插入/更新。我找到了一种使用linq
DataContext
的ChangeSet
(DataContext.GetChangeSet().Deletes
,DataContext.GetChangeSet().Inserts
,等等)的方法,我已经发布了它们作为答案。这里的问题是您同时插入了它们。在实际调用db.SubmitChanges()之前,它们都不存在
尝试在循环中移动db.SubmitChanges()
,这样应该可以解决问题
ETA:另一种可能是将您的循环更改为:
foreach (var value in values)
到
我不确定这是否只是您的问题中的一个输入错误,但您的LINQ语句中的Where子句是
。Where(x=>x.Value=Value)
。我想这里需要的是比较运算符,而不是赋值运算符。尝试将LINQ语句更改为以下内容:
var dbItem = db.Items
.Where(x => x.Value == value)
.SingleOrDefault();
此外,如果您使用的是.NET 3.5或更高版本,则可以将
列表替换为,以确保只有唯一的值。我找到了一种使用DataContext的变更集在linq sql中工作的方法,而不是修复数据。示例中的数据很简单,但它可能是一个对象图,它会命中多个表,并且很难修复
我首先查看db.Items
,然后检查DataContext的变更集(db.GetChangeSet().Inserts
)以找到该项,如果找不到则插入
void MultipleInserts(List<int> values)
{
using (var db = new DBDataContext())
{
foreach (var value in values)
{
// look in db first
var dbItem = db.Items
.Where(x => x.Value == value)
.SingleOrDefault();
if (dbItem == null)
{
// look in ChangeSet second
var cachedItem = db.GetChangeSet().Inserts
.OfType<Item>()
.Where(x => x.Value == value)
.SingleOrDefault();
if (cachedItem == null)
{
var Item = new Item()
{
Value = value
};
db.Items.InsertOnSubmit(Item);
}
}
}
db.SubmitChanges();
}
}
void multipleinsert(列表值)
{
使用(var db=new DBDataContext())
{
foreach(值中的var值)
{
//先查看数据库
var dbItem=db.Items
.其中(x=>x.Value==Value)
.SingleOrDefault();
if(dbItem==null)
{
//第二次查看变更集
var cachedItem=db.GetChangeSet().Inserts
第()类
.其中(x=>x.Value==Value)
.SingleOrDefault();
if(cachedItem==null)
{
变量项=新项()
{
价值=价值
};
db.Items.InsertOnSubmit(项目);
}
}
}
db.SubmitChanges();
}
}
Eric,我理解。我必须做多次插入。我不能做单个插入。@hlpPy-刚刚更新了我的答案。或者,您可以在dbml中将该属性标记为唯一的(虽然已经有一段时间了,但记不清您是如何做到这一点的)我实际上在两列上有一个唯一的索引(我简化了这个问题)。在这种情况下,dbml技巧中的那个独特属性将不起作用。Jon,这是微不足道的-但是HashSet
是在3.5中引入的。
var dbItem = db.Items
.Where(x => x.Value == value)
.SingleOrDefault();
void MultipleInserts(List<int> values)
{
using (var db = new DBDataContext())
{
foreach (var value in values)
{
// look in db first
var dbItem = db.Items
.Where(x => x.Value == value)
.SingleOrDefault();
if (dbItem == null)
{
// look in ChangeSet second
var cachedItem = db.GetChangeSet().Inserts
.OfType<Item>()
.Where(x => x.Value == value)
.SingleOrDefault();
if (cachedItem == null)
{
var Item = new Item()
{
Value = value
};
db.Items.InsertOnSubmit(Item);
}
}
}
db.SubmitChanges();
}
}