Partager via


Sérialisation (LINQ to SQL)

Mise à jour : November 2007

Cette rubrique décrit les fonctions de sérialisation de LINQ to SQL. Les paragraphes qui suivent fournissent des informations sur l'ajout de la sérialisation pendant la génération de code au moment du design et le comportement de sérialisation à l'exécution de classes LINQ to SQL.

Vous pouvez ajouter du code de sérialisation au moment du design selon l'un des méthodes suivantes :

  • Dans le Concepteur Objet/Relationnel, affectez la valeur Unidirectional à la propriété Serialization Mode.

  • Sur la ligne de commande SQLMetal, ajoutez l'option /serialization. Pour plus d'informations, consultez Outil de génération de code (SqlMetal.exe).

Vue d'ensemble

Le code généré par LINQ to SQL fournit des fonctions de chargement différé par défaut. Le chargement différé est très utile au niveau intermédiaire pour le chargement transparent de données à la demande. Il pose toutefois problème pour la sérialisation car le sérialiseur déclenche un chargement différé, qu'il soit voulu ou non. En effet, lorsqu'un objet est sérialisé, sa fermeture transitive dans toutes les références à chargement différé en sortie est sérialisée.

La fonctionnalité de sérialisation de LINQ to SQL traite ce problème, principalement par le biais de deux mécanismes :

Définitions

  • Sérialiseur DataContract : sérialiseur par défaut utilisé par le composant Windows Communication Framework (WCF) du .NET Framework 3.0 ou versions ultérieures.

  • Sérialisation unidirectionnelle :version sérialisée d'une classe qui contient uniquement une propriété d'association unidirectionnelle (pour éviter un cycle). Par convention, la propriété sur le côté parent d'une relation de clé primaire-étrangère est marquée pour sérialisation. L'autre côté d'une association bidirectionnelle n'est pas sérialisé.

    La sérialisation unidirectionnelle est le seul type de sérialisation pris en charge par LINQ to SQL.

Exemple de code

Le code suivant utilise les classes Customer et Order standard de l'exemple de base de données Northwind et montre comment ces classes sont décorées avec les attributs de sérialisation.

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

Pour la classe Order de l'exemple suivant, seule la propriété d'association inverse correspondant à la classe Customer est montrée, par souci de concision. Elle n'a pas d'attribut DataMember pour éviter un cycle.

' 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

Comment sérialiser les entités

Vous pouvez sérialiser les entités dans les codes présentés dans la section précédente (voir ci-dessous).

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

Relations auto-récursives

Les relations auto-récursives suivent le même modèle. La propriété d'association qui correspond à la clé étrangère n'a pas d'attribut DataMember, contrairement à la propriété parente.

Observez la classe suivante, qui présente deux relations auto-récursives : Employee.Manager/Reports et 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;

Voir aussi

Tâches

Procédure : rendre les entités sérialisables (LINQ to SQL)

Référence

Outil de génération de code (SqlMetal.exe)

Autres ressources

Informations générales (LINQ to SQL)