使用guid主键忽略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. 主键是Guid(uniqueidentifier)

这是表格的样子:

  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缺陷?

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

请参阅连接#381883: https ://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx ?反馈ID = 381883

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

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

您可以通过编写以下内容来清理它:

  [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; } 

您是否尝试过使用存储属性?

 [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 */ } 

另请参见基于属性的映射(LINQ to SQL)

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

 [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。

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

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