代码之家  ›  专栏  ›  技术社区  ›  Todd Ropog

LINQ to SQL能否在插入时省略未指定的列,以便使用数据库默认值?

  •  11
  • Todd Ropog  · 技术社区  · 16 年前

    我有一个不可为空的数据库列,它有一个默认值集。插入行时,有时为列指定值,有时不指定值。当省略列时,这在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)和这样的表时。我想产生相同的行为,但我不知道如何让L2这样做。我希望能够运行以下代码,让第一行获取我指定的值,第二行从数据库获取默认值:

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

    如果col1的auto-generated value属性为false,则会根据需要创建第一行,但第二行失败,col1上出现空错误。如果auto-generated value为true,则使用数据库中的默认值创建这两行。我尝试过自动生成值、自动同步和可以为空的各种组合,但是我没有尝试过提供我想要的行为。

    当没有指定值时,L2S不会从INSERT语句中省略列。相反,它是这样做的:

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

    …这当然会导致第1列出现空错误。

    如果没有给定值,有没有方法让L2S从insert语句中省略列?还是有其他方法来达到我想要的行为?我需要数据库级别的默认值,因为并非所有的行插入都是通过L2S完成的,而且在某些情况下,默认值比硬编码值(例如,基于另一个字段创建默认值)要复杂一些,因此我宁愿避免复制该逻辑。

    2 回复  |  直到 16 年前
        1
  •  7
  •   Jeff Schumacher    16 年前

    不幸的是,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的实体,您希望PhoneNumberDesc字段的默认值为“home”,则可以通过以下方式实现它:

        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
  •  -2
  •   KM.    16 年前

    我不确定Linq,但在SQL中,如果您希望使用默认值,请使用以下任何一种方法:

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

    INSERT INTO Table1 (col1, col2) VALUES (DEFAULT, 'X')  
    
    推荐文章