Serialisierung (LINQ to SQL)

Aktualisiert: November 2007

In diesem Abschnitt werden die Serialisierungsfähigkeiten von LINQ to SQL beschrieben. Die folgenden Abschnitte enthalten Informationen zum Hinzufügen von Serialisierung während der Codeerstellung zur Entwicklungszeit sowie zum Serialisierungsverhalten von LINQ to SQL-Klassen zur Laufzeit.

Sie können zur Entwurfszeit durch eine der folgenden Methoden Serialisierungscode hinzufügen:

  • Ändern Sie in O/R-Designer die Serialisierungsmodus-Eigenschaft in Unidirektional.

  • Fügen Sie in der SQLMetal-Befehlszeile die /serialization-Option hinzu. Weitere Informationen finden Sie unter Tool zur Codegenerierung (SqlMetal.exe).

Übersicht

Der von LINQ to SQL erzeugte Code bietet standardmäßig die Möglichkeit zum verzögerten Laden. Verzögertes Laden ist auf der Mittelebene eine komfortable Möglichkeit zum transparenten, bedarfsorientierten Laden der Daten. Bei der Serialisierung kommt es jedoch zu Problemen, da hierbei das verzögerte Laden auch dann ausgelöst wird, wenn dieses nicht beabsichtigt ist. Wird ein Objekt serialisiert, wird sein transitiver Abschluss unter allen ausgehenden verzögert geladenen Verweisen serialisiert.

Das LINQ to SQL-Serialisierungsfeature behebt dieses Problem vor allem durch zwei Mechanismen:

Definitionen

  • DataContract Serializer: Standard-Serializer der Windows Communication Framework (WCF)-Komponente von .NET Framework 3.0 oder höher.

  • Unidirektionale Serialisierung: Die serialisierte Version einer Klasse enthält nur eine Einweg-Zuordnungseigenschaft (um einen Zyklus zu vermeiden). Laut Konvention wird die Eigenschaft auf der übergeordneten Seite einer primären Fremdschlüsselbeziehung für die Serialisierung markiert. Die andere Seite in einer bidirektionalen Zuordnung wird nicht serialisiert.

    Unidirektionale Serialisierung ist der einzige Serialisierungstyp, der von LINQ to SQL unterstützt wird.

Codebeispiel

Im folgenden Beispiel werden die herkömmlichen Klassen Customer und Order aus der Beispieldatenbank Northwind verwendet. Es wird gezeigt, wie diese Klassen mit Serialisierungsattributen versehen werden.

' The class is decorated with the DataContract attribute.
<Table(Name:="dbo.Customers"),  _
 DataContract()>  _
Partial Public Class Customer
    Implements System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged
// The class is decorated with the DataContract attribute.
[Table(Name="dbo.Customers")]
[DataContract()]
public partial class Customer : INotifyPropertyChanging, INotifyPropertyChanged
{
    ' Private fields are not decorated with any attributes,
    ' and are elided.
    Private _CustomerID As String

    ' Public properties are decorated with the DataMember
    ' attribute and the Order property specifying the
    ' serial number. See the Order class later in this topic
    ' for exceptions
    <Column(Storage:="_CustomerID", DbType:="NChar(5) NOT NULL", CanBeNull:=false, IsPrimaryKey:=true),  _
     DataMember(Order:=1)>  _
    Public Property CustomerID() As String
        Get
            Return Me._CustomerID
        End Get
        Set
            If ((Me._CustomerID = value)  _
                        = false) Then
                Me.OnCustomerIDChanging(value)
                Me.SendPropertyChanging
                Me._CustomerID = value
                Me.SendPropertyChanged("CustomerID")
                Me.OnCustomerIDChanged
            End If
        End Set
    End Property
    // Private fields are not decorated with any attributes, and are
    // elided.
    private string _CustomerID;

    // Public properties are decorated with the DataMember
    // attribute and the Order property specifying the serial
    // number. See the Order class later in this topic for
    // exceptions.
    public Customer()
    {
        this.Initialize();
    }
    
    [Column(Storage="_CustomerID", DbType="NChar(5) NOT NULL", CanBeNull=false, IsPrimaryKey=true)]
    [DataMember(Order=1)]
    public string CustomerID
    {
        get
        {
            return this._CustomerID;
        }
        set
        {
            if ((this._CustomerID != value))
            {
                this.OnCustomerIDChanging(value);
                this.SendPropertyChanging();
                this._CustomerID = value;
                this.SendPropertyChanged("CustomerID");
                this.OnCustomerIDChanged();
            }
        }
    }
   ' The following Association property is decorated with
   ' DataMember because it is the parent side of the
   ' relationship. The reverse property in the Order
   ' class does not have a DataMember attribute. This
   ' factor prevents a 'cycle.'
   <Association(Name:="FK_Orders_Customers", Storage:="_Orders", OtherKey:="CustomerID", DeleteRule:="NO ACTION"), _
 DataMember(Order:=13)> _
Public Property Orders() As EntitySet(Of [Order])
       Get
           Return Me._Orders
       End Get
       Set(ByVal value As EntitySet(Of [Order]))
           Me._Orders.Assign(Value)
       End Set
   End Property
    // The following Association property is decorated with
    // DataMember because it is the parent side of the
    // relationship. The reverse property in the Order class
    // does not have a DataMember attribute. This factor
    // prevents a 'cycle.'
    [Association(Name="FK_Orders_Customers", Storage="_Orders", OtherKey="CustomerID", DeleteRule="NO ACTION")]
    [DataMember(Order=13)]
    public EntitySet<Order> Orders
    {
        get
        {
            return this._Orders;
        }
        set
        {
            this._Orders.Assign(value);
        }
    }

Für die Order-Klasse im folgenden Beispiel wird aus Gründen der Übersicht nur die umgekehrte Zuordnungseigenschaft entsprechend der Customer-Klasse dargestellt. Das DataMember-Attribut zur Vermeidung eines Zyklus fehlt.

' The class for the Orders table is also decorated with the
' DataContract attribute.
<Table(Name:="dbo.Orders"),  _
 DataContract()>  _
Partial Public Class [Order]
    Implements System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged
// The class for the Orders table is also decorated with the
// DataContract attribute.
[Table(Name="dbo.Orders")]
[DataContract()]
public partial class Order : INotifyPropertyChanging, INotifyPropertyChanged
    ' Private fields for the Orders table are not decorated with
    ' any attributes, and are elided.
    Private _CustomerID As String

    ' Public properties are decorated with the DataMember
    ' attribute.
    ' The reverse Association property on the side of the
    ' foreign key does not have the DataMember attribute.
    <Association(Name:="FK_Orders_Customers", Storage:="_Customer", ThisKey:="CustomerID", IsForeignKey:=true)>  _
    Public Property Customer() As Customer
    // Private fields for the Orders table are not decorated with
    // any attributes, and are elided.
    private int _OrderID;

    // Public properties are decorated with the DataMember
    // attribute.
    // The reverse Association property on the side of the
    // foreign key does not have the DataMember attribute.
    [Association(Name = "FK_Orders_Customers", Storage = "_Customer", ThisKey = "CustomerID", IsForeignKey = true)]
    public Customer Customer

So serialisieren Sie die Entitäten

Sie können die Entitäten im Code im vorherigen Abschnitt wie folgt serialisieren:

Dim db As New Northwnd("...")

Dim cust = (From c In db.Customers _
           Where c.CustomerID = "ALFKI").Single

Dim dcs As New DataContractSerializer(GetType(Customer))

Dim sb As StringBuilder = New StringBuilder()
Dim writer As XmlWriter = XmlWriter.Create(sb)
dcs.WriteObject(writer, cust)
writer.Close()
Dim xml As String = sb.ToString()
Northwnd db = new Northwnd(@"c\northwnd.mdf");

Customer cust = db.Customers.Where(c => c.CustomerID ==
    "ALFKI").Single();

DataContractSerializer dcs = 
    new DataContractSerializer(typeof(Customer));
StringBuilder sb = new StringBuilder();
XmlWriter writer = XmlWriter.Create(sb);
dcs.WriteObject(writer, cust);
writer.Close();
string xml = sb.ToString();

Selbstrekursive Beziehungen

Selbstrekursive Beziehungen folgen dem gleichen Muster. Die dem Fremdschlüssel entsprechende Zuordnungseigenschaft weist im Gegensatz zur übergeordneten Eigenschaft kein DataMember-Attribut auf.

Beachten Sie die folgende Klasse, die über zwei selbstrekursive Beziehungen verfügt: Employee.Manager/Reports und Employee.Mentor/Mentees.

' No DataMember attribute
Public Manager As Employee
<DataMember(Order:=3)> _
Public Reports As EntitySet(Of Employee)

' No DataMember attribute
Public Mentor As Employee
<DataMember(Order:=5)> _
Public Mentees As EntitySet(Of Employee)
// No DataMember attribute.
public Employee Manager;
[DataMember(Order = 3)]
public EntitySet<Employee> Reports;

// No DataMember
public Employee Mentor;
[DataMember(Order = 5)]
public EntitySet<Employee> Mentees;

Siehe auch

Aufgaben

Gewusst wie: Aktivieren der Serialisierbarkeit von Entitäten (LINQ to SQL)

Referenz

Tool zur Codegenerierung (SqlMetal.exe)

Weitere Ressourcen

Hintergrundinformationen (LINQ to SQL)