共用方式為


LINQ to SQL 中的串行化

本文說明LINQ to SQL串行化功能。 接下來的段落將說明如何在設計時於程式碼產生時加入序列化,以及 LINQ 在執行時序列化到 SQL 類別的行為。

您可以在設計時間新增串行化程式代碼,方法是下列其中一種方法:

  • 在對象關係型設計工具中,將 [串行化模式 ] 屬性變更為 [單向]。

  • 在 SQLMetal 命令行上,新增 /serialization 選項。 如需詳細資訊,請參閱 SqlMetal.exe(程式代碼產生工具)。

概觀

LINQ to SQL 所產生的程式代碼預設會提供延後載入功能。 延遲載入在中介層上非常方便,以便視需要透明載入數據。 不過,串行化有問題,因為串行化程式會觸發延後載入,不論是否要延遲載入。 實際上,當物件串行化時,其所有輸出延遲載入參考下的可轉移關閉都會串行化。

LINQ to SQL 串行化功能可解決此問題,主要是透過兩種機制:

定義

  • DataContract 串行化程式:.NET Framework 3.0 或更新版本的 Windows Communication Framework (WCF) 元件所使用的預設串行化程式。

  • 單向串行化:只包含單向關聯屬性的類別串行化版本(以避免迴圈)。 依照慣例,在主鍵-外鍵關係中,父端的屬性會標示為序列化。 雙向關聯的另一端不會被序列化。

    單向串行化是LINQ to SQL 唯一支援的串行化類型。

程式代碼範例

下列程式代碼會使用 Northwind 範例資料庫中的傳統 CustomerOrder 類別,並示範這些類別如何以串行化屬性裝飾。

// 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類別對應的反向關聯屬性。 它沒有 DataMemberAttribute 屬性可避免迴圈。

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

如何序列化實體

您可以在上一節所示的程式代碼中串行化實體,如下所示:

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 關聯性

自我遞歸關聯性遵循相同的模式。 對應至外鍵的關聯屬性沒有 DataMemberAttribute 屬性,而父屬性則為 。

請考慮具有兩個自我遞歸關聯性的下列類別:Employee.Manager/Reports 和 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)

另請參閱