2009-04-07 8 views
5

SQL Server veritabanımda düzenli olarak bazı veriler eklemek zorundayım. Ancak veriyi okuduğum beslemeler, daha önce eklenen bazı verileri tekrarlar. DB'ye eklemek için Linq-to-SQL kullandığımda, bazı veriler çoğaltılır veya birincil anahtara bağlı olarak birincil anahtar ihlali istisnası kaldırılır.Linq-to-SQL kullanarak yeni kayıtlar nasıl eklenir?

Yinelenen veriler olmadan ve istisnasız veriler nasıl eklenir? Bir istisna ile istisnadan kaçınmak istemiyorum, çünkü istisna kaldırıldığında verilerin geri kalanı eklenmez.

güncelleme Ben de kendi çözüm bulundu: Birazdan

cevap

6

Eğer sınıfın yeni bir örneğini oluşturmak yapmanız gereken tek şey ve InsertAllOnSubmit + SubmitChanges sonra çalıştırılır Silme işlemi saklanan bir çift girişleri yazdı sonra masaya() InsertOnSumbit arayın: Eğer kimlik sütunu artırmak nasıl olduğunu

var foo = new MyFoo { Name = "foo1" }; 
var dc = new MyDataContext(); 
dc.Foos.InsertOnSubmit(foo); 
dc.SubmitChanges(); 

sen emin olmak gerekir başka bir şey değildir. Genel olarak, ID sütunlarımdaki IDENTITY (1,1) ayarını kullandığınızdan her zaman emin oluyorum. Bu yüzden sevdiği LINQ varlığın kimliği sütunu ilan şöyle:

[Column(AutoSync = AutoSync.OnInsert, IsPrimaryKey = true, IsDbGenerated = true)] 
public Int32 Id { get; set; } 

yinelemeleri önlemek için, gerçekten ihtiyacınız ne bir işlevsellik "ekleyin" my dükkanda diyoruz. IMHO, bu en kolay bir saklı yordam ile gerçekleştirilir - biz bile bunun için kullandığımız bir şablon var:

USE [<Database_Name, sysobject, Database_Name>] 
GO 

CREATE PROCEDURE [<Schema, sysobject, dbo>].[<Table_Name, sysobject, Table_Name>__append] 
(
    @id INT OUTPUT, 
    @<Key_Param, sysobject, Key_Param> <Key_Param_Type, sysobject, VARCHAR(50)> 
) 
AS 
BEGIN 

     SELECT @id = [id] FROM [<Schema, sysobject, dbo>].[<Table_Name, sysobject, Table_Name>s] (NOLOCK) WHERE [<Key_Param, sysobject, Key_Param>] = @<Key_Param, sysobject, Key_Param> 

IF @id IS NULL 
BEGIN  
    INSERT INTO [<Schema, sysobject, dbo>].[<Table_Name, sysobject, Table_Name>s] ([<Key_Param, sysobject, Key_Param>]) 
    OUTPUT INSERTED.[id] INTO @inserted_ids 
    VALUES (@<Key_Param, sysobject, Key_Param>) 

    SELECT TOP 1 @id = [id] FROM @inserted_ids; 
END 
ELSE 
BEGIN 
    UPDATE [<Schema, sysobject, dbo>].[<Table_Name, sysobject, Table_Name>s] 
    SET 
     [<Key_Param, sysobject, Key_Param>] = @<Key_Param, sysobject, Key_Param> 
    WHERE [id] = @id 
END 
END 
GO 

O linq içinde olsa da, sadece varolan kimliklerinin listesi için sorgu mümkündür (veya ne olursa olsun sütunu) servisle dışına:

var dc = new MyDataContext(); 
var existingFoos = dc.Foos.ToList(); 
var newFoos = new List<Foo>(); 
foreach(var bar in whateverYoureIterating) { 
// logic to add to newFoos 
} 
var foosToInsert = newFoos.Where(newFoo => !existingFoos.Any(existingFoo => newFoo.Id == existingFoo.Id)); 

dc.Foos.InsertAllOnSubmit(foosToInsert); 
dc.SubmitChanges(); 
// use the next line if you plan on re-using existingFoos. If that's the case I'd wrap dc.SubmitChanges() in a try-catch as well. 
existingFoos.AddRange(foosToInsert); 
+0

düzenlemenizi bekliyoruz ... –

+0

LINQ çözümü oldukça yavaş görünüyor. Devasa bir tabloyu sorgulamak için içeriğin belleğe yüklenmesi sorgulanamaz görünüyor. Belki de SP yaklaşımına bağlı kalmalıyım. –

+1

Ben de böyle düşündüm ... Yine de, sadece ID sütunu gibi sadece ihtiyacınız olan özellikleri seçerek LINQ çözümünü hızlandırabilirsiniz. Ayrıca, birden çok çalıştırma için "var olan" sorguyu yeniden kullanabiliyorsanız, bu da yardımcı olur. –

1

Ne yazık ki, insert gerçekleştirmeden önce veritabanını kontrol etmez SQL Linq olarak etrafında hiçbir yolu yoktur. Bunu yapmanın tek yolu, yinelenen kaydın bulunup bulunmadığını belirlemek için ilk veritabanını sorgulamak ve ardından kaydetmediyse kaydı eklemektir.

İdeal olarak, Linq to SQL, SQL sütununda Ignore Duplicate Keys özelliğini destekleyecektir. Ama maalesef şu anda değil.