使用guid主键忽略LINQ to SQL实体列名称属性

时间:2009-07-01 04:29:39

标签: c# sql-server linq sql-server-2005 linq-to-sql

我正在使用LINQ to SQL的简单实体类(SQL Server 2005 SP3 x64)。

[Table( Name="TBL_REGISTRATION" )]
public sealed class Registration : IDataErrorInfo
{
    [Column( Name = "TBL_REGISTRATION_PK", IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert )]
    public Guid RegistrationID { get; private set; }
    /* other properties ommited for brevity */
}

这里只有两件有趣的事情:

  1. 类名和属性名与表名和列名
  2. 不同
  3. 主键是Guid(uniqueidentifier)
  4. 这是表格的样子:

     create table dbo.TBL_REGISTRATION
        (
        TBL_REGISTRATION_PK uniqueidentifier primary key clustered
            rowguidcol
            default newid(),
        /* other columns ommited for brevity */ 
        )
    

    当我将此实体附加到我的表并在我的DataContext上提交更改时,LINQ堆栈会抛出一个SqlException:

    SqlException(0x80131904):无效的列名称“RegistrationID”

    LINQ似乎忽略了我的RegistrationID属性上的Column(Name =“TBL_REGISTRATION_PK”)属性。我花了一些时间用不同的属性装饰试图让它工作。最后,我决定使用一个私有的TBL_REGISTRATION_PK属性来包装我的RegistrationID属性,以使LINQ满意。

    [Table( Name="TBL_REGISTRATION" )]
    public sealed class Registration : IDataErrorInfo
    {
            public Guid RegistrationID { get; private set; }
            [Column( IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert )]
            private Guid TBL_REGISTRATION_PK { get { return RegistrationID; } set { RegistrationID = value; } }
        /* other properties ommited for brevity */
    }
    

    这很有效。

    为什么它不是第一种方式?我在这里做错了还是LINQ缺陷?

5 个答案:

答案 0 :(得分:6)

这是Linq-to-SQL中的一个错误。它在.net 4.0中修复。

请参阅Connect#381883: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=381883

答案 1 :(得分:2)

您的财产需要从'私人套餐'中删除'私人';在VS 2008中创建短手属性而不实现get / set时,编译器会为您创建私有成员变量(知道的名称)。 ColumnAttribute中的Storage选项指定要使用的私有成员。

Linq to SQL不知道如何设置属性,如果你将setter标记为private并公开getter(不要问我为什么)。如果您希望只读取您的属性,请像上面一样创建一个私有成员变量。

您可以通过以下方式进行清理来清理它:

    [Table( Name="TBL_REGISTRATION" )]
    public sealed class Registration : IDataErrorInfo
    {
            public Guid RegistrationID { get { return _registrationID; } }

            [Column( IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
            private Guid _registrationID; 
}

答案 2 :(得分:0)

您是否尝试过使用Storage属性?

[Table( Name="TBL_REGISTRATION" )]
public sealed class Registration : IDataErrorInfo
{
        [Column( Name="TBL_REGISTRATION_PK", Storage="_RegistrationID", IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert )]
        public Guid RegistrationID { get { return _RegistrationID; } set { _RegistrationID = value; } }

        private Guid _RegistrationID;
    /* other properties ommited for brevity */
}

另见Attribute-Based Mapping (LINQ to SQL)

答案 3 :(得分:0)

使用“存储”属性,以及列的名称:

[Column( Name="TBL_REGISTRATION_PK", Storage="TBL_REGISTRATION_PK", IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert )]
        public Guid RegistrationID { get { return _RegistrationID; } set { _RegistrationID = value; } }

因为列的存储名称是TBL_REGISTRATION_PK。

答案 4 :(得分:0)

我发现此问题的最佳解决方案是在类中创建一个私有Guid字段,该字段与数据库中的主键具有完全相同的名称,并将其用作符合该属性的属性的支持字段框架指南命名约定。

// Primary key to TBL_REGISTRATIONT
[Column( Name = "TBL_REGISTRATIONT_PK", IsDbGenerated = true, AutoSync = AutoSync.OnInsert )]
public Guid RegistrationID
{
    get
    {
        return TBL_REGISTRATIONT_PK;
    }
    private set
    {
        TBL_REGISTRATIONT_PK = value;
    }
}
[Column( IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert )]
private Guid TBL_REGISTRATIONT_PK;