使用英语阅读

通过


LINQ to SQL 中的序列化

本文介绍 LINQ to SQL 序列化功能。 后面的段落提供有关如何在设计时在代码生成期间添加序列化以及 LINQ to SQL 类的运行时序列化行为的信息。

可以通过以下任一方法在设计时添加序列化代码:

  • 在对象关系设计器中,将 序列化模式 属性更改为 单向

  • 在 SQLMetal 命令行上,添加 /serialization 选项。 有关详细信息,请参阅 SqlMetal.exe(代码生成工具)

概述

LINQ to SQL 生成的代码默认提供延迟加载功能。 延迟加载在中间层上非常方便,以便按需透明加载数据。 但是,序列化存在问题,因为序列化程序会触发延迟加载,无论是否打算延迟加载。 实际上,对对象进行序列化时,会对其在所有出站延迟加载引用下的可传递闭包进行序列化。

LINQ to SQL 序列化功能主要通过两种机制解决此问题:

定义

  • DataContract 序列化程序:.NET Framework 3.0 或更高版本的 Windows 通信框架 (WCF) 组件使用的默认序列化程序。

  • 单向序列化:仅包含单向关联属性的类的序列化版本(以避免循环)。 按照约定,主键-外键关系的父级端的属性标记为序列化。 双向关联的另一端未序列化。

    单向序列化是 LINQ to SQL 支持的唯一序列化类型。

代码示例

以下代码使用 Northwind 示例数据库中的传统 Customer 类和 Order 类,并演示如何使用序列化属性修饰这些类。

C#
// The class is decorated with the DataContract attribute.
[Table(Name="dbo.Customers")]
[DataContract()]
public partial class Customer : INotifyPropertyChanging, INotifyPropertyChanged
{
C#
// 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();
        }
    }
}
C#
// 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);
    }
}

Order对于以下示例中的类,为了简洁起见,只显示与Customer类对应的反向关联属性。 它没有用来避免出现循环的 DataMemberAttribute 属性。

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

如何序列化实体

可以在上一部分所示的代码中序列化实体,如下所示:

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

Self-Recursive 人际关系

自我递归关系遵循相同的模式。 与外键对应的关联属性没有属性 DataMemberAttribute ,而父属性则具有该属性。

请考虑以下具有两个自递归关系的类:Employee.Manager/Reports 和 Employee.Mentor/Mentees。

C#
// 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;

另请参阅


其他资源

培训

模块

存储和检索 JSON 文件 - Training

了解如何使用 JsonSerializer 类、JsonSerializerOptions 类和数据传输对象,对 JavaScript 对象表示法 (JSON) 字符串进行序列化和反序列化。

活动

.NET Conf 2025

11月10日 3时 - 11月10日 3时

.NET 10 在 .NET Conf 2025 上发布! 收听 .NET 社区,庆祝和了解 11 月 11 日至 13 日的新版本。

保存日期