Может ли LINQ-to-SQL опускать неуказанные столбцы при вставке, чтобы использовать значение по умолчанию для базы данных?

У меня есть столбец базы данных, не содержащий NULL, который имеет значение по умолчанию. При вставке строки иногда указывается значение для столбца, иногда это не так. Это отлично работает в TSQL, когда столбец опущен. Например, учитывая следующую таблицу:

CREATE TABLE [dbo].[Table1](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [col1] [nvarchar](50) NOT NULL,
    [col2] [nvarchar](50) NULL,
CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ([id] ASC)
)
GO
ALTER TABLE [dbo].[Table1] 
    ADD CONSTRAINT [DF_Table1_col1] DEFAULT ('DB default') FOR [col1]

Следующие два оператора будут работать:

INSERT INTO Table1 (col1, col2) VALUES ('test value', '')  
INSERT INTO Table1 (col2) VALUES ('')     

Во втором выражении значение по умолчанию используется для col1.

Проблема заключается в использовании LINQ-to-SQL (L2S) со следующей таблицей. Я хочу создать такое же поведение, но я не могу понять, как сделать L2S. Я хочу, чтобы иметь возможность запускать следующий код и иметь первую строку получить значение, которое я указываю, а вторая строка получает значение по умолчанию из базы данных:

var context = new DataClasses1DataContext();
var row1 = new Table1 { col1 = "test value", col2 = "" };
context.Table1s.InsertOnSubmit(row1);
context.SubmitChanges();
var row2 = new Table1 { col2 = "" };
context.Table1s.InsertOnSubmit(row2);
context.SubmitChanges();

Если свойство Auto Generated Value для col1 является False, первая строка создается по желанию, но вторая строка выходит из строя с нулевой ошибкой на col1. Если значение Auto Generated Value равно True, обе строки создаются со значением по умолчанию из базы данных. Я пробовал различные комбинации Auto Generated Value, Auto-Sync и Nullable, но ничего, что я пробовал, дает поведение, которое я хочу.

L2S не пропускает столбец из инструкции insert, когда значение не указано. Вместо этого он делает что-то вроде этого:

INSERT INTO Table1 (col1, col2) VALUES (null, '')

... который, конечно, вызывает ошибку null на col1.

Есть ли способ заставить L2S опустить столбец из инструкции insert, если значение не задано? Или есть какой-то другой способ получить поведение, которое я хочу? Мне нужно значение по умолчанию на уровне базы данных, потому что не все вставки строк выполняются через L2S, а в некоторых случаях значение по умолчанию немного сложнее, чем жестко закодированное значение (например, создание значения по умолчанию на основе другого поля), поэтому я бы скорее избегайте дублирования этой логики.

Ответ 1

К сожалению, Linq to SQL не поддерживает значения базы данных по умолчанию. См. Первый вопрос здесь:

http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/3ae5e457-099e-4d13-9a8b-df3ed4ba0bab/

Что они предлагают, так это то, что вы предоставляете реализацию метода Insert для рассматриваемого объекта. Подпись

partial void Insert[EntityName](Entity instance)

Итак, если у вас есть объект под названием Person, вы хотели иметь значение по умолчанию для "Home" для поля PhoneNumberDesc, вы можете реализовать его следующим образом:

    partial void InsertPerson(Person instance)
    {
        if (string.IsNullOrEmpty(instance.PhoneNumberDesc))
            instance.PhoneNumberDesc = "Home";

        var insertParams = new List<object>();
        var insertStatement = "insert into ...";

        // build the rest of the insert statement and fill in the parameter values here...

        this.ExecuteQuery(typeof(Person), insertStatement, insertParams.ToArray());
    }

Возможно, вам удастся избежать события OnCreated, которое вызывается с каждым конструктором для каждого объекта. В этой статье немного объясняется, как точки расширяемости в Linq To SQL: http://msdn.microsoft.com/en-us/library/bb882671.aspx

В целом, решение действительно отстойно. Удачи!

Ответ 2

Я не уверен в LINQ, но в SQL, когда вы хотите по умолчанию сделать это в любом случае:

INSERT INTO Table1 (col2) VALUES ('X')  

или

INSERT INTO Table1 (col1, col2) VALUES (DEFAULT, 'X')