Как вставить только новые записи с помощью Linq-to-S'L?

Я должен периодически вставлять некоторые данные в мою базу данных сервера S'L. Но каналы, где я читал данные повторяет некоторые данные, которые были вставлены раньше. При использовании Linq-to-S-SL для вставки в DB либо некоторые данные дублируются, либо повышается основное исключение с нарушением ключа, в зависимости от основного ключа.

Как вставить данные без дублирования и без исключений? Я не хочу, чтобы избежать исключения с try-catch, потому что как только исключение поднято остальные данные не вставляется.

обновление Я также нашел свое собственное решение: я написал дублированные записи удаления сохранены процедуры, которая проводится сразу после InsertAllOnSubmit и SubmitChanges

Ответ на: "Как вставить только новые записи с помощью Linq-to-S'L?"

Количество ответов:2

Все, что вам нужно сделать, это создать новый экземпляр вашего класса, а затем позвонить InsertOnSumbit () на столе:

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

Другое, что вам нужно быть уверенным в том, как вы прибавляете ваш ID колонке. В общем, я всегда не могу использовать параметр IDENTITY (1,1) в столбцах ID. Это заявлено на id колонке вашего объекта LIN, как так:

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

Чтобы избежать дубликатов, что вам действительно нужно, это то, что мы называем в моем магазине "приложение" функциональность. IMHO, это наиболее легко осуществляется с сохраненной процедурой - у нас даже есть шаблон, который мы используем для него:

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

Можно сделать это в linq, хотя, просто запрос на список существующих ID (или любой колонке вы keying от):

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);

К сожалению, нет никакого способа обойти его, как Linq к S'L не проверяет базу данных, прежде чем он выполняет вставку. Единственный способ сделать это — запросить базу данных сначала , чтобы определить, существует ли дубликат записи, а затем добавить запись, если она этого не делает.

В идеале Linq в СЗЛ будет поддерживать Ignore Duplicate Keys property on a SQL column. But unfortunately it does not at the moment. собственности на колонке S'L. Но, к сожалению, на данный момент этого не происходит.