2009-07-01 11 views
11

Estaba trabajando con una clase de entidad simple con LINQ to SQL (SQL Server 2005 SP3 x64).Atributo de nombre de columna de entidad de LINQ a SQL ignorado con la clave principal de guid

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

Sólo hay dos cosas poco interesantes aquí:

  1. Los nombres de las clases y de propiedad no son los mismos que los nombres de tablas y columnas
  2. La clave principal es un GUID (uniqueidentifier)

Esto es lo que se ve la mesa como:

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

Cuando hay que adjuntar a esta entidad a mi mesa y incluir cambios en mi DataContext, la pila LINQ lanza de nuevo un SqlException:

SqlException (0x80131904): nombre de columna no válido 'RegistrationID'

LINQ parece ignorar el atributo Column (Name = "TBL_REGISTRATION_PK") en mi propiedad RegistrationID. Pasé un tiempo inmóvil con diferentes decoraciones de atributos tratando de hacer que funcione. Al final me decidí por una propiedad TBL_REGISTRATION_PK privada para envolver mi propiedad RegistrationID y hacer feliz a 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 */ 
} 

Esto funciona.

¿Por qué no funcionó de la primera manera? ¿Estoy haciendo algo mal aquí o es un defecto LINQ?

Respuesta

0

¿Ha intentado utilizar la propiedad 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 */ 
} 

Véase también Attribute-Based Mapping (LINQ to SQL)

+0

Nop. Buena idea pero eso definitivamente no funciona: "Nombre de columna inválido 'RegistrationID'." –

0

uso del "almacenamiento" de la propiedad, con el nombre de la columna:

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

Dado que el nombre de almacenamiento de la columna es TBL_REGISTRATION_PK.

+0

Gracias por jugar pero eso no funciona. Causará la emisión de una InvalidOperationException en tiempo de ejecución porque no hay ningún campo o propiedad "TBL_REGISTRATION_PK" en la clase. La propiedad ColumnAttribute.Storage es para indicar un campo privado que contiene los datos que respaldan la propiedad que está decorando con el atributo. –

2

Su propiedad necesita ser 'privada' eliminada de 'conjunto privado'; Cuando realiza las propiedades de mano corta en VS 2008 sin implementar get/set, el compilador crea variables de miembro privadas para usted (cuyo nombre, quién sabe). La opción de Almacenamiento en ColumnAttribute especifica qué miembro privado usar.

Linq to SQL no sabe cómo establecer la propiedad si marca el setter como privado y tiene el getter public (no me pregunte por qué). Si desea hacer que su propiedad sea de solo lectura, cree una variable de miembro privada como la que hizo anteriormente.

Se puede limpiar escribiéndolo como la siguiente:

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

¿Esto resuelve su problema? – jonathanpeppers

0

La mejor solución que he encontrado a este problema es crear un campo Guid privado en la clase que tiene el mismo nombre exacto la clave principal en la base de datos y utilícela como el campo de respaldo para la propiedad que cumple con las convenciones de nomenclatura de la Guía del Marco.

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