СериализацияSerialization

В этом разделе описываются LINQ to SQLLINQ to SQL возможности сериализации.This topic describes LINQ to SQLLINQ to SQL serialization capabilities. В приведенных ниже подразделах приводятся сведения о добавлении сериализации в процессе создания кода во время разработки, а также о поведении классов LINQ to SQLLINQ to SQL при сериализации во время выполнения.The paragraphs that follow provide information about how to add serialization during code generation at design time and the run-time serialization behavior of LINQ to SQLLINQ to SQL classes.

Код сериализации можно добавить во время разработки одним из перечисленных ниже методов.You can add serialization code at design time by either of the following methods:

  • В реляционный конструктор объектов измените свойство режим сериализации на однонаправленный.In the Object Relational Designer, change the Serialization Mode property to Unidirectional.

  • В командной строке SQLMetal добавьте параметр /Serialization .On the SQLMetal command line, add the /serialization option. Дополнительные сведения см. в разделе SQLMetal.exe (средство создания кода).For more information, see SqlMetal.exe (Code Generation Tool).

ОбзорOverview

Код, формируемый, LINQ to SQLLINQ to SQL предоставляет возможности отложенной загрузки по умолчанию.The code generated by LINQ to SQLLINQ to SQL provides deferred loading capabilities by default. Отложенная загрузка - очень удобное средство среднего уровня для прозрачной загрузки данных по требованию.Deferred loading is very convenient on the mid-tier for transparent loading of data on demand. Однако при сериализации с этим средством возникают проблемы, поскольку сериализатор инициирует отложенную загрузку независимо от намерений пользователя.However, it is problematic for serialization, because the serializer triggers deferred loading whether deferred loading is intended or not. В действительности, при сериализации объекта также сериализуется его транзитивное замыкание для всех исходящих ссылок с отложенной загрузкой.In effect, when an object is serialized, its transitive closure under all outbound defer-loaded references is serialized.

LINQ to SQLLINQ to SQLФункция сериализации решает эту проблему, в первую очередь, с помощью двух механизмов:The LINQ to SQLLINQ to SQL serialization feature addresses this problem, primarily through two mechanisms:

ОпределенияDefinitions

  • Сериализатор DataContract: сериализатор по умолчанию, используемый компонентом Windows Communication Framework (WCF) платформа .NET Framework 3,0 или более поздних версий.DataContract serializer: Default serializer used by the Windows Communication Framework (WCF) component of the .NET Framework 3.0 or later versions.

  • Однонаправленная сериализация: сериализованная версия класса, которая содержит только одностороннее свойство взаимосвязи (во избежание цикла).Unidirectional serialization: The serialized version of a class that contains only a one-way association property (to avoid a cycle). По соглашению, для сериализации помечается свойство родительской стороны отношения «первичный ключ - внешний ключ».By convention, the property on the parent side of a primary-foreign key relationship is marked for serialization. Другая сторона, участвующая в двунаправленном отношении, не сериализуется.The other side in a bidirectional association is not serialized.

    Однонаправленная сериализация является единственным типом сериализации, поддерживаемым технологией LINQ to SQLLINQ to SQL.Unidirectional serialization is the only type of serialization supported by LINQ to SQLLINQ to SQL.

Пример кодаCode Example

В представленном ниже коде используются традиционные классы Customer и Order из учебной базы данных « Northwind" и демонстрируется, как добавить к этим классам атрибуты сериализации.The following code uses the traditional Customer and Order classes from the Northwind sample database, and shows how these classes are decorated with serialization attributes.

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

Для краткости в следующем примере для класса Order показано только обратное свойство отношения, соответствующее классу Customer.For the Order class in the following example, only the reverse association property corresponding to the Customer class is shown for brevity. Этот класс не имеет атрибута DataMemberAttribute, чтобы избежать зацикливания.It does not have a DataMemberAttribute attribute to avoid a cycle.

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

Сериализация сущностейHow to Serialize the Entities

Сущности в коде, показанном в предыдущих примерах, можно сериализовать следующим образом:You can serialize the entities in the codes shown in the previous section as follows;

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

Саморекурсивные отношенияSelf-Recursive Relationships

Саморекурсивные отношения следуют тому же шаблону.Self-recursive relationships follow the same pattern. Свойство отношения, соответствующее внешнему ключу, не имеет атрибута DataMemberAttribute, в то время как родительское свойство этот атрибут имеет.The association property corresponding to the foreign key does not have a DataMemberAttribute attribute, whereas the parent property does.

Рассмотрим следующий класс, содержащий две саморекурсивные связи: Employee.Manager/Reports и Employee.Mentor/Mentees.Consider the following class that has two self-recursive relationships: Employee.Manager/Reports and 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)

См. такжеSee also