使用 Visual Studio 将对象绑定为 .NET Framework 应用程序中的数据源

注释

此类 DataSet 和相关类是 2000 年代初的旧版 .NET Framework 技术,使应用程序能够在应用与数据库断开连接时处理内存中的数据。 这些技术对于使用户能够修改数据并将更改保留回数据库的应用特别有用。 尽管数据集是经过证实的成功技术,但新 .NET 应用程序的建议方法是使用 Entity Framework Core。 Entity Framework 提供了一种更自然的方式来将表格数据用作对象模型,并且具有更简单的编程接口。

Visual Studio 提供设计时工具,用于将自定义对象用作应用程序中的数据源。 如果要将数据从数据库存储在绑定到 UI 控件的对象中时,建议的方法是使用 Entity Framework 生成类或类。 Entity Framework 自动生成所有样本更改跟踪代码,这意味着在 DbSet 对象上调用 AcceptChanges 时,对本地对象所做的任何更改都会自动保存到数据库。 有关详细信息,请参阅 Entity Framework 文档

小窍门

仅当应用程序已基于数据集时,才应考虑本文中对象绑定的方法。 如果你已经熟悉数据集,并且要处理的数据是表格的,而不是太复杂或太大,也可以使用这些方法。 有关更简单的示例,使用 DataReader 直接将数据加载到对象中,并在不进行数据绑定的情况下手动更新 UI,请参阅 使用 ADO.NET 创建简单的数据应用程序

对象要求

自定义对象在 Visual Studio 中使用数据设计工具的唯一要求是对象至少需要一个公共属性。

通常,自定义对象不需要任何特定的接口、构造函数或属性来充当应用程序的数据源。 但是,如果要将对象从 “数据源 ”窗口拖动到设计图面以创建数据绑定控件,并且如果对象实现 ITypedListIListSource 接口,该对象必须具有默认构造函数。 否则,Visual Studio 无法实例化数据源对象,在将项拖动到设计图面时会显示错误。

将自定义对象用作数据源的示例

尽管在将对象用作数据源时,可以通过无数方法实现应用程序逻辑,但对于 SQL 数据库,可以使用 Visual Studio 生成的 TableAdapter 对象简化一些标准作。 本页介绍如何使用 TableAdapters 实现这些标准进程。 它不是创建自定义对象的指南。 例如,无论对象的具体实现或应用程序的逻辑如何,通常都会执行以下标准作:

  • 将数据加载到对象中(通常来自数据库)。

  • 创建对象的类型化集合。

  • 向集合中添加和删除对象。

  • 在表单上向用户显示对象数据。

  • 更改/编辑对象中的数据。

  • 将数据从对象保存回数据库。

将数据加载到对象中

在本示例中,使用 TableAdapters 将数据加载到对象中。 默认情况下,TableAdapters 是使用两种方法创建的,这些方法从数据库提取数据并填充数据表。

  • 该方法 TableAdapter.Fill 使用返回的数据填充现有数据表。

  • 该方法 TableAdapter.GetData 返回填充了数据的新数据表。

使用数据加载自定义对象的最简单方法是调用 TableAdapter.GetData 该方法,循环访问返回的数据表中的行集合,并使用每行中的值填充每个对象。 可以创建一个 GetData 方法,该方法返回添加到 TableAdapter 的任何查询的填充数据表。

注释

Visual Studio 将 TableAdapter 查询FillGetData命名为默认名称,但可以将这些名称更改为任何有效的方法名称。

以下示例演示如何循环访问数据表中的行,并使用数据填充对象:

private void LoadCustomers()
{
    NorthwindDataSet.CustomersDataTable customerData = 
        customersTableAdapter1.GetTop5Customers();
    
    foreach (NorthwindDataSet.CustomersRow customerRow in customerData)
    {
        Customer currentCustomer = new Customer();
        currentCustomer.CustomerID = customerRow.CustomerID;
        currentCustomer.CompanyName = customerRow.CompanyName;

        if (customerRow.IsAddressNull() == false)
        {
            currentCustomer.Address = customerRow.Address;
        }

        if (customerRow.IsCityNull() == false)
        {
            currentCustomer.City = customerRow.City;
        }

        if (customerRow.IsContactNameNull() == false)
        {
            currentCustomer.ContactName = customerRow.ContactName;
        }

        if (customerRow.IsContactTitleNull() == false)
        {
            currentCustomer.ContactTitle = customerRow.ContactTitle;
        }

        if (customerRow.IsCountryNull() == false)
        {
            currentCustomer.Country = customerRow.Country;
        }

        if (customerRow.IsFaxNull() == false)
        {
            currentCustomer.Fax = customerRow.Fax;
        }

        if (customerRow.IsPhoneNull() == false)
        {
            currentCustomer.Phone = customerRow.Phone;
        }

        if (customerRow.IsPostalCodeNull() == false)
        {
            currentCustomer.PostalCode = customerRow.PostalCode;
        }

        if (customerRow.IsRegionNull() == false)
        {
            currentCustomer.Region = customerRow.Region;
        }

        LoadOrders(currentCustomer);
        customerBindingSource.Add(currentCustomer);
    }
}

创建对象的类型化集合

可以为对象创建集合类,或使用 BindingSource 组件自动提供的类型化集合。

为对象创建自定义集合类时,我们建议从BindingList<T>继承。 此泛型类提供管理集合的功能,并支持引发事件以向 Windows 窗体中的数据绑定基础结构发送通知。

BindingSource 中自动生成的集合使用 BindingList<T> 作为其类型集合。 如果您的应用程序不需要其他功能,您可以在BindingSource中维护集合。 有关详细信息,请参阅 List 类的属性 BindingSource

注释

如果集合需要基本实现 BindingList<T>不提供的功能,则应创建自定义集合,以便根据需要添加到类。

以下代码演示如何为对象的强类型集合 Order 创建类:

/// <summary>
/// A collection of Orders
/// </summary>
public class Orders: System.ComponentModel.BindingList<Order>
{
    // Add any additional functionality required by your collection.
}

将对象添加到集合

通过调用 Add 自定义集合类的方法或 BindingSource 方法,将对象添加到集合中。

注释

BindingList<T> 继承时,会自动为自定义集合提供 Add方法。

以下代码演示如何将对象添加到类型化的集合中 BindingSource

Customer currentCustomer = new Customer();
customerBindingSource.Add(currentCustomer);

以下代码演示如何将对象添加到继承自 BindingList<T>的类型化集合:

注释

在此示例中,集合 Orders 是对象的属性 Customer

Order currentOrder = new Order();
currentCustomer.Orders.Add(currentOrder);

从集合中删除对象

通过调用自定义集合类的RemoveRemoveAt方法,或者BindingSource来从集合中删除对象。

注释

BindingList<T> 继承时,会自动为自定义集合提供 RemoveRemoveAt 方法。

以下代码演示如何使用RemoveAt该方法查找和删除类型化集合中的BindingSource对象:

int customerIndex = customerBindingSource.Find("CustomerID", "ALFKI");
customerBindingSource.RemoveAt(customerIndex);

向用户显示对象数据

若要向用户显示对象中的数据,请使用 “数据源配置 ”向导创建对象数据源,然后从 “数据源 ”窗口中将整个对象或单个属性拖到窗体上。

修改对象中的数据

若要编辑绑定到 Windows 窗体控件的自定义对象中的数据,只需编辑绑定控件中的数据(或直接在对象的属性中)。 数据绑定体系结构更新对象中的数据。

如果应用程序需要跟踪更改并将建议的更改回滚到其原始值,则必须在对象模型中实现此功能。 有关数据表如何跟踪建议的更改、请参阅DataRowStateHasChangesGetChanges的示例。

将对象中的数据保存回数据库

通过将对象中的值传递到 TableAdapter 的 DBDirect 方法,将数据保存回数据库。

Visual Studio 创建可以直接针对数据库执行的 DBDirect 方法。 这些方法不需要 DataSet 或 DataTable 对象。

TableAdapter DBDirect 方法 DESCRIPTION
TableAdapter.Insert 将新记录添加到数据库,允许将单个列值作为方法参数传入。
TableAdapter.Update 更新数据库中的现有记录。 Update 方法采用原始列值和新列值作为方法参数。 原始值用于查找原始记录,新值用于更新该记录。

该方法TableAdapter.Update还用于将数据集中的更改协调回数据库,通过将DataSetDataTableDataRowDataRow数组作为方法参数。
TableAdapter.Delete 根据作为方法参数传入的原始列值从数据库中删除现有记录。

若要保存对象集合中的数据,请遍历对象的集合(例如,使用 for-next 循环)。 使用 TableAdapter 的 DBDirect 方法将每个对象的值发送到数据库。

以下示例演示如何使用 TableAdapter.Insert DBDirect 方法将新客户直接添加到数据库中:

private void AddNewCustomers(Customer currentCustomer)
{
    customersTableAdapter.Insert( 
        currentCustomer.CustomerID, 
        currentCustomer.CompanyName, 
        currentCustomer.ContactName, 
        currentCustomer.ContactTitle, 
        currentCustomer.Address, 
        currentCustomer.City, 
        currentCustomer.Region, 
        currentCustomer.PostalCode, 
        currentCustomer.Country, 
        currentCustomer.Phone, 
        currentCustomer.Fax);
}