Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ to SQL entity column name attribute ignored with guid primary key

I was working with a simple entity class with 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 */
}

There are only two somewhat interesting things here:

  1. The class and property names aren't the same as the table and column names
  2. The primary key is a Guid (uniqueidentifier)

Here's what the table looks like:

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

When I attach this entity to my table and submit changes on my DataContext, the LINQ stack throws back a SqlException:

SqlException (0x80131904): Invalid column name 'RegistrationID'

LINQ seems to be ignoring the Column( Name = "TBL_REGISTRATION_PK" ) attribute on my RegistrationID property. I spent a while futzing with different attribute decorations trying to get it to work. In the end I settled on a private TBL_REGISTRATION_PK property to wrap my RegistrationID property to make LINQ happy.

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

This works.

Why didn't it work the first way? Am I doing something wrong here or is this a LINQ defect?

like image 752
Brian Reiter Avatar asked Jul 01 '09 04:07

Brian Reiter


2 Answers

This is a bug in Linq-to-SQL. It is fixed in .net 4.0.

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

like image 98
KristoferA Avatar answered Oct 03 '22 23:10

KristoferA


Your property needs 'private' removed from 'private set;' When you make the short hand properties in VS 2008 without implementing get/set, the compiler creates private member variables for you (of which name who knows). The Storage option in ColumnAttribute specifies which private member to use.

Linq to SQL doesn't know how to set the property if you mark the setter private and have the getter public (don't ask me why). If you wish to make your property readonly, make a private member variable like you did above.

You can clean it up by writing it like the following:

    [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; 
}
like image 20
jonathanpeppers Avatar answered Oct 03 '22 23:10

jonathanpeppers