C# 使用guid主键忽略LINQ到SQL实体列名属性
我使用的是一个简单的实体类,使用LINQ to SQL(SQL Server 2005 SP3 x64) 这里只有两件有趣的事情:C# 使用guid主键忽略LINQ到SQL实体列名属性,c#,sql-server,linq,sql-server-2005,linq-to-sql,C#,Sql Server,Linq,Sql Server 2005,Linq To Sql,我使用的是一个简单的实体类,使用LINQ to SQL(SQL Server 2005 SP3 x64) 这里只有两件有趣的事情: 类名和属性名与表名和列名不同 主键是Guid(唯一标识符) 下面是该表的外观: create table dbo.TBL_REGISTRATION ( TBL_REGISTRATION_PK uniqueidentifier primary key clustered rowguidcol default newid
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似乎忽略了my RegistrationID属性上的列(Name=“TBL\u REGISTRATION\u 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缺陷?您尝试过使用该属性吗
[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 */
}
另请参见使用带有列名称的“存储”属性:
[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。您的属性需要从“private set;”中删除“private”当您在VS2008中创建简写属性而不实现get/set时,编译器将为您创建私有成员变量(谁知道它的名称)。ColumnAttribute中的存储选项指定要使用的私有成员 如果将setter标记为private并将getter设置为public(不要问我为什么),linqtosql不知道如何设置属性。如果希望将属性设置为只读,请像上面那样设置私有成员变量 您可以通过如下方式编写它来清理它:
[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;
}
我发现解决这个问题的最佳解决方案是在类中创建一个私有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;
这是LINQtoSQL中的一个bug。它在.NET4.0中是固定的 参见Connect#381883:
没有。好主意,但这显然不起作用:“无效的列名'RegistrationID'。”感谢您的参与,但这不起作用。它将导致在运行时引发InvalidOperationException,因为类中没有“TBL_REGISTRATION_PK”字段或属性。ColumnAttribute.Storage属性用于指示一个私有字段,该字段保存支持使用该属性装饰的属性的数据。我很高兴终于发现(a)我没有疯,(b)它正在被修复。
// 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;