Serialisering i LINQ till SQL
I den här artikeln beskrivs linq-till-SQL-serialiseringsfunktioner. Följande stycken innehåller information om hur du lägger till serialisering under kodgenerering vid designtillfället och körnings serialiseringsbeteendet för LINQ till SQL-klasser.
Du kan lägga till serialiseringskod vid designtillfället med någon av följande metoder:
I objektrelationsdesignern ändrar du egenskapen Serialiseringsläge till Unidirectional.
Lägg till alternativet /serialisering på kommandoraden SQLMetal. Mer information finns i SqlMetal.exe (kodgenereringsverktyg).
Översikt
Koden som genereras av LINQ till SQL ger funktioner för uppskjuten inläsning som standard. Uppskjuten inläsning är mycket praktiskt på mellannivån för transparent inläsning av data på begäran. Det är dock problematiskt för serialisering, eftersom serialiseraren utlöser uppskjuten inläsning oavsett om uppskjuten inläsning är avsedd eller inte. När ett objekt serialiseras serialiseras i själva verket dess transitiva stängning under alla utgående uppskjutna referenser serialiseras.
Funktionen LINQ till SQL-serialisering åtgärdar det här problemet, främst genom två mekanismer:
Ett DataContext läge för att stänga av uppskjuten inläsning (ObjectTrackingEnabled). Mer information finns i DataContext.
En kodgenereringsväxel för att generera System.Runtime.Serialization.DataContractAttribute och System.Runtime.Serialization.DataMemberAttribute attribut på genererade entiteter. Den här aspekten, inklusive beteendet för att skjuta upp inläsningsklasser under serialisering, är det viktigaste ämnet i det här avsnittet.
Definitioner
DataContract serializer: Standard serialiserare som används av WCF-komponenten (Windows Communication Framework) i .NET Framework 3.0 eller senare versioner.
Enkelriktad serialisering: Den serialiserade versionen av en klass som endast innehåller en envägsassociationegenskap (för att undvika en cykel). Enligt konventionen markeras egenskapen på den överordnade sidan av en primär-sekundär nyckelrelation för serialisering. Den andra sidan i en dubbelriktad association serialiseras inte.
Enkelriktad serialisering är den enda typen av serialisering som stöds av LINQ till SQL.
Kodexempel
Följande kod använder traditionella Customer
klasser och Order
klasser från Northwind-exempeldatabasen och visar hur dessa klasser är dekorerade med serialiseringsattribut.
// 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
För klassen i följande exempel visas endast egenskapen omvänd association som motsvarar Customer
klassen med korthet. Det har DataMemberAttribute inget attribut för att undvika en cykel.
// 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
Serialisera entiteterna
Du kan serialisera entiteterna i koderna som visas i föregående avsnitt på följande sätt.
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()
Självrekursiva relationer
Självrekursiva relationer följer samma mönster. Associationsegenskapen som motsvarar den externa nyckeln har DataMemberAttribute inget attribut, medan den överordnade egenskapen har det.
Tänk på följande klass som har två självrekursiva relationer: 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)