2013-12-22 45 views
2

我正在使用LINQ以及Entity-Framework在SQL Server 2012数据库中插入一些数据。实体框架一次插入多行时忽略重复主键值

我正在插入数据的数据库表有一个主键,我一次插入大约1000条记录。

这是我检索一组1000行中的数据,并出于性能原因一次保存1000行。

现在的问题是,我可能偶尔会获得这1000行中的任何行的重复值,当发生这种情况时,没有任何行保存在数据库中。

有什么办法,我可以只是默默地忽略那一行,而不是插入它,而所有其他非重复行插入?

另外我也尝试在每次插入之前查询数据库,但性能成本太高。

+0

在Sql Table本身中不能有重复的主键,因此实体框架无法做到这一点,约束不应该绕过但受到尊重,将用户操作排队到可以并行完成的作业中,用户移动到别的东西上。许多方式来处理这个,而不会忽略数据的完整性 –

回答

0

有什么办法可以只是默默地忽略那一行,而不插入它,而所有其他非重复行插入?

如果您可以在SQL Server中重新创建索引,则可以忽略重复项。插入后重新创建索引而不使用ignore_dups,因为它的速度更快。

CREATE TABLE [dbo].[YourTable](
    [id] [int] NOT NULL, 
PRIMARY KEY CLUSTERED 
(
    [id] ASC 
)WITH (IGNORE_DUP_KEY = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
0

我建议你在插入语句之前做一些额外的处理,没有任何代码离开我会尝试用伪代码向你展示。

ICollection<record> myRecords = Service.GetMyRecords(); 
//your processing logic before the insert 
ICollection<record> recordsToInsert =Service.BusinessLogic(myRecords); 

foreach(var record in recordsToInsert) 
{ 
    if(myRecords.Contains(record) 
    { 
     recordsToInsert.Remove(record); 
    } 
} 

这应该可以确保您在recordsToInsert集合中没有记录会使您的数据库跳闸。这也为您节省了尝试插入语句,因为它不会尝试并失败。

+0

问题是表有150万+记录,并检查是否有任何记录是一个耗时的过程。 – FatalTouch

+0

然后我会建议更改DB上的设置以正确处理此问题,因为这似乎是运行时成本最低的解决方案; user3123649建议了一种方法来做到这一点。 –

0

做一个查询第一,检查的新记录的任何是否存在像这样:

var checks = records.Select(r => r.Id).ToArray(); 
if (!context.Records.Any(r => check.Contains(r.Id)) 
{ 
    // do the insert 
} 

第一检查后,你可以细化检查,以找出其中的1000条记录是罪魁祸首。所以这个快乐场景总是很快。只有在找到重复的情况下,该过程才会变慢。

在运行一个事务时,您无法指示EF默默忽略一个数据库异常。