2009-07-01 7 views
11

Ich arbeitete mit einer einfachen Entitätsklasse mit LINQ to SQL (SQL Server 2005 SP3 x64).LINQ to SQL Entitätsspaltenname Attribut ignoriert mit GUID Primärschlüssel

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

Es gibt nur zwei etwas Interessantes hier:

  1. die Klassen- und Eigenschaftsnamen sind nicht die gleichen wie die Tabellen- und Spaltennamen
  2. Der Primärschlüssel ist ein Guid (unique)

Hier ist, was die Tabelle wie folgt aussieht:

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

Wenn ich diese Einheit an meinen Tisch befestigen und senden Sie Änderungen auf meinem Datacontext, wirft die LINQ-Stack eine SqlException zurück:

SqlException (0x80131904): Ungültige Spaltenname

‚RegistrationID‘

LINQ zu sein scheint zu ignorieren Das Attribut "Column (Name =" TBL_REGISTRATION_PK ") für meine Eigenschaft" RegistrationID ". Ich verbrachte eine Weile damit, verschiedene Attribute zu dekorieren, um es zum Laufen zu bringen. Am Ende entschied ich mich für eine private TBL_REGISTRATION_PK -Eigenschaft, um meine Eigenschaft "RegistrationID" zu verpacken, um LINQ glücklich zu machen.

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

Dies funktioniert.

Warum hat es nicht die erste Möglichkeit funktioniert? Mache ich hier etwas falsch oder ist das ein LINQ-Defekt?

Antwort

0

Haben Sie versucht, die Storage Eigenschaft zu verwenden?

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

Siehe auch Attribute-Based Mapping (LINQ to SQL)

+0

Nope. Gute Idee, aber das funktioniert definitiv nicht: "Ungültiger Spaltenname 'RegistrationID'." –

0

Verwenden Sie das "Storage" Eigentum, mit dem Namen der Spalte:

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

Da der Speicher Name der Spalte TBL_REGISTRATION_PK ist.

+0

Danke fürs Spielen, aber das geht nicht. Dies führt dazu, dass eine InvalidOperationException zur Laufzeit ausgelöst wird, da in der Klasse kein Feld oder Eigenschaft "TBL_REGISTRATION_PK" vorhanden ist. Die ColumnAttribute.Storage-Eigenschaft gibt ein privates Feld an, das die Daten enthält, die die Eigenschaft unterstützen, die Sie mit dem Attribut dekorieren. –

2

Ihre Immobilie muss 'privat' von 'private set' entfernt sein; Wenn Sie in VS 2008 die Eigenschaften short hand erstellen, ohne get/set zu implementieren, erstellt der Compiler private Membervariablen für Sie (deren Name bekannt ist). Die Speicheroption in ColumnAttribute gibt an, welches private Member verwendet werden soll.

Linq to SQL weiß nicht, wie man die Eigenschaft setzt, wenn Sie den Setter privat markieren und den Getter öffentlich machen (fragen Sie mich nicht warum). Wenn Sie Ihre Property nur readonly erstellen möchten, erstellen Sie eine private Member-Variable wie oben.

Sie können es aufzuräumen, indem es wie das Schreiben folgende:

[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

Löst dies Ihr Problem? – jonathanpeppers

0

Die beste Lösung, die ich für dieses Problem gefunden haben, ist ein privates Guid Feld in der Klasse zu erstellen, die den gleichen Namen hat wie der Primärschlüssel in der Datenbank und verwenden Sie diesen als Hintergrundfeld für die Eigenschaft, die den Namenskonventionen der Framework-Richtlinie entspricht.

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