Атрибут имени столбца объекта LINQ to SQL игнорируется с помощью первичного ключа guid

Я работал с простым классом сущностей с 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 */
}

Здесь всего две интересные вещи:

  • Имена классов и свойств не совпадают с именами таблиц и столбцов
  • Первичный ключ - это 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, похоже, игнорирует атрибут Column (Name = "TBL_REGISTRATION_PK" ) в моем свойстве RegistrationID. Я провел некоторое время с разными атрибутами атрибутов, пытаясь заставить его работать. В конце концов я остановился на частном свойстве 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?

Ответ 2

Ваша собственность нуждается 'private' удалена из 'private set;' Когда вы создаете свойства короткой руки в VS 2008 без реализации get/set, компилятор создает для вас частные переменные-члены (имя которых известно). Опция Storage в ColumnAttribute указывает, какой частный член использовать.

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

Ответ 3

Вы пытались использовать свойство 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 */
}

См. также Отображение на основе атрибутов (LINQ to SQL)

Ответ 4

Используйте свойство "Хранение" с именем столбца:

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

Ответ 5

Лучшим решением, которое я нашел для этой проблемы, является создание частного класса Guid в классе с таким же именем, что и первичный ключ в базе данных, и использовать его в качестве поля поддержки для свойства, которое соответствует Соглашения о присвоении имен в рамках Framework.

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