Freigeben über


Serialisierung in LINQ to SQL

In diesem Artikel werden LINQ to SQL-Serialisierungsfunktionen beschrieben. Die folgenden Abschnitte enthalten Informationen zum Hinzufügen der Serialisierung während der Codeerstellung zur Entwurfszeit 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 im Objektrelational-Designer die Serialisierungsmoduseigenschaft in "Unidirectional".

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

Überblick

Der von LINQ to SQL generierte Code stellt standardmäßig verzögerte Ladefunktionen bereit. Verzögertes Laden ist sehr bequem auf der mittleren Ebene für das transparente Laden von Daten bei Bedarf. Für die Serialisierung ist es jedoch problematisch, da der Serialisierer verzögertes Laden auslöst, ob das verzögerte Laden beabsichtigt ist oder nicht. Wird ein Objekt serialisiert, wird sein transitiver Abschluss unter allen ausgehenden verzögert geladenen Verweisen serialisiert.

Das LINQ to SQL-Serialisierungsfeature behebt dieses Problem in erster Linie über zwei Mechanismen:

Definitionen

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

  • Unidirektionale Serialisierung: Die serialisierte Version einer Klasse, die nur eine unidirektionale Zuordnungseigenschaft enthält (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.

    Die unidirektionale Serialisierung ist der einzige Typ der Serialisierung, der von LINQ to SQL unterstützt wird.

Codebeispiel

Der folgende Code verwendet die herkömmlichen Customer Klassen und Order Klassen aus der Northwind-Beispieldatenbank und zeigt, wie diese Klassen mit Serialisierungsattributen versehen werden.

// The class is decorated with the DataContract attribute.
[Table(Name="dbo.Customers")]
[DataContract()]
public partial class Customer : INotifyPropertyChanging, INotifyPropertyChanged
{
' The class is decorated with the DataContract attribute.
<Table(Name:="dbo.Customers"),  _
 DataContract()>  _
Partial Public Class Customer
    Implements System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged
// 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();
        }
    }
}
' 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
// 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);
    }
}
   ' 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

Für die Order Klasse im folgenden Beispiel wird nur die umgekehrte Zuordnungseigenschaft, die der Customer Klasse entspricht, aus Platzgründen angezeigt. Es verfügt nicht über ein DataMemberAttribute Attribut, um einen Zyklus zu vermeiden.

// The class for the Orders table is also decorated with the
// DataContract attribute.
[Table(Name="dbo.Orders")]
[DataContract()]
public partial class Order : INotifyPropertyChanging, INotifyPropertyChanged
' 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
// 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
' 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

So serialisieren Sie die Entitäten

Sie können die Entitäten in den im vorherigen Abschnitt gezeigten Codes wie folgt serialisieren.

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();
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()

Selbstrekursive Beziehungen

Selbst rekursive Beziehungen folgen demselben Muster. Die Zuordnungseigenschaft, die dem Fremdschlüssel entspricht, besitzt kein DataMemberAttribute-Attribut, während die übergeordnete Eigenschaft eines besitzt.

Betrachten Sie die folgende Klasse mit zwei selbstrekursiven Beziehungen: Employee.Manager/Reports und Employee.Mentor/Mentees.

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

Siehe auch