65.9K
CodeProject 正在变化。 阅读更多。
Home

社交俱乐部:使用 WinForms、C#.NET、ADO.NET 和 MS Access 的示例应用程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (74投票s)

2013年6月17日

CPOL

11分钟阅读

viewsIcon

406117

downloadIcon

29084

使用 C#、ADO.NET 和 MS Access 开发的 WinForms 应用程序

目录

Social club

引言

本文介绍了一个使用 C# 开发的简单 Windows 数据库应用程序。它使用 WinForms 作为前端 (UI),MS Access 作为后端 (DB)。该应用程序名为“社交俱乐部”,用于创建和管理俱乐部成员的信息。

该应用程序的用户界面 (UI) 包含几个屏幕 (登录、注册、管理)。注册屏幕用于创建/注册新的俱乐部会员。管理屏幕提供了编辑、删除、搜索、打印俱乐部成员信息和导出数据到 Excel 的选项。本文将重点介绍如何在示例演示项目中应用某些主题;例如 3 层架构、连接到 Access 数据库、为 Access 数据库创建基本 SQL 语句、编写 ADO.NET 代码、使用 WinForms 和 C#.NET 实现 CURD 操作。

软件环境

应用程序在以下软件环境中开发

  • 开发环境:Visual Studio.NET 2010
  • 框架:.NET Framework 4.0
  • 用户界面:Windows Forms
  • 编程语言:C#.NET
  • 数据访问:ADO.NET
  • 数据库:MS Access 2010
  • 代码分析工具:Stylecop

先决条件

您需要在您的机器上安装以下工具才能运行示例应用程序。

  • Microsoft Visual Studio 2010
  • Microsoft Access 2010

分层架构

3-Tier

表示层

表示层 (桌面) 是最顶层的,包含应用程序的用户界面。此层负责将信息传递给用户和应用程序。它包含用于用户交互的窗体 (UI) 和用于处理事件的代码隐藏 (UI 逻辑)。

数据层

数据层是中间层,包含业务服务方法、数据访问逻辑、数据模型和 SQL 脚本。

业务服务

业务服务包含与数据访问通信的方法。它充当表示逻辑和数据访问逻辑之间的桥梁。此层负责调用数据访问方法并将结果返回给表示层。

Data Model

数据模型包含反映数据的属性;这通常称为实体/业务对象。

SQL 脚本

SQL 脚本包含承载数据库逻辑的 SQL 语句。

数据访问

数据访问通常包含访问数据库数据的逻辑,并且通常在单独的类库项目中实现。在演示项目中,业务服务和数据访问实现在同一个类库中。

数据库层

数据库层包含具有表结构和数据的数据库。

项目结构

解决方案资源管理器显示了项目内的目录结构。解决方案包含两个项目。

桌面 (Windows 项目)

桌面项目是一个 Windows Forms 应用程序项目,包含窗体 (UI) 和相应的代码隐藏 (.CS) 文件。代码隐藏文件包含处理事件的 UI 逻辑。

数据 (库项目)

数据项目是一个类库项目,包含数据库逻辑 (SQL 脚本)、数据访问逻辑 (ADO.NET 代码) 和数据模型 (业务实体)。所有服务方法和与数据相关的逻辑都驻留在同一个类库中。在多层架构系统中,最好将这些分别放在单独的类库项目中,并在需要时将库项目引用到相应的项目中。

3-Tier

以这种方式组织文件夹、文件、项目可以将代码分成不同的部分,使每个部分处理不同的关注点。这是将程序分成部分的原则。这使得代码可重用、可读、易于管理和维护。

创建数据库

社交俱乐部应用程序只需要一个表来存储俱乐部成员信息。下面显示的图像显示了设计视图中的数据库。它显示了左侧面板中的表以及右侧面板中的详细信息 (字段名称、数据类型、描述)。可以通过右侧面板下方的“常规”选项卡设置每个字段的属性。

Database design view

以下是在 MS Access 2010 中创建数据库的步骤

  1. 打开 MS Access 并单击“空白数据库”模板 (这将打开一个新的空白数据库,左侧面板中有一个默认表“Table1”。
  2. 右键单击表并转到设计视图 (将弹出一个小窗口要求保存表)
  3. 为表命名 (在本例中,表名为“ClubMember”),然后单击“保存”。
  4. 创建具有必要数据类型、属性和描述的字段 (列)。
  5. 5. 在“文件”菜单中单击“另存为”选项,然后通过提供适当的名称保存数据库 (在本例中,数据库名称为“SocialClub”)。数据库将另存为 {filename}.accdb 文件。

设置项目

我假设您对 Visual Studio 环境有一定的了解。在此我将列出设置桌面和数据项目的步骤。

  1. 打开 Visual Studio,选择 文件 -> 新建 -> 项目
  2. 在新建项目窗口中,从“其他项目类型”模板中选择“Visual Studio 解决方案”
  3. 将项目名称命名为“SocialClub”,然后单击“确定”。
  4. 右键单击解决方案,然后选择 添加 -> 新建项目
  5. 在新建项目窗口中,从模板中选择 Visual C# -> Windows -> Windows Forms 应用程序
  6. 将项目名称命名为“SocialClub.Desktop”,然后单击“确定”。
  7. 再次右键单击解决方案,然后选择 添加 -> 新建项目
  8. 在新建项目窗口中,从模板中选择 Visual C# -> Windows -> 类库
  9. 将项目名称命名为“SocialClub.Data”,然后单击“确定”。
  10. 在“SocialClub.Desktop”项目中,右键单击“引用”,然后选择“添加引用”。
  11. 在“添加引用”窗口中,选择“项目”选项卡 -> SocialClub.Data 项目,然后单击“确定”。
  12. 按 CTRL+SHFT+B 并检查应用程序是否可以生成。
  13. 将数据库文件 (SocialClub.accdb) 复制到应用程序启动路径下的 bin 目录。

现在,您已在 Visual Studio 中设置了项目,并准备开始编码。下面是步骤 11 的 Visual Studio 屏幕截图。

Visual Studio

实现数据层

命名常量 (枚举)

为字段 (健康状况、婚姻状况、职业) 创建了一组命名常量 (枚举)。数据库中的这些字段将包含枚举值的数字等效项,并且数据模型中的这些字段将是相应的枚举类型。此外,这些枚举值 (字符串等效值) 将显示在 UI 的下拉列表中供选择。

类图

Enums

示例代码

/// <summary>
/// Enum for Health status
/// </summary>
public enum HealthStatus
{
    Excellent = 1,
    Good,
    Average,
    Poor
}
/// <summary>
/// Enum for Marital status
/// </summary>
public enum MaritalStatus
{
    Married = 1,
    Single
}
/// <summary>
/// Enum for Occupation
/// </summary>
public enum Occupation
{
    Doctor = 1,
    Engineer,
    Professor,
}

数据模型 (实体)

我们需要在项目中拥有业务实体/模型,该模型将包含反映数据库表中字段的属性。此实体将用作数据传输对象 (DTO),仅用于在层之间传输数据。下面显示了为示例应用程序创建的数据模型。

类图

Data Model

代码

/// <summary>
/// ClubMemberModel class
/// </summary>
public class ClubMemberModel
{
    /// <summary>
    /// Gets or sets member id
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// Gets or sets member name
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// Gets or sets date of birth
    /// </summary>
    public DateTime DateOfBirth { get; set; }
    /// <summary>
    /// Gets or sets occupation
    /// </summary>
    public Occupation Occupation { get; set; }
        
    /// <summary>
    /// Gets or sets marital status
    /// </summary>
    public MaritalStatus MaritalStatus { get; set; }
    /// <summary>
    /// Gets or sets health status
    /// </summary>
    public HealthStatus HealthStatus { get; set; }
    /// <summary>
    /// Gets or sets salary
    /// </summary>
    public decimal Salary { get; set; }
    /// <summary>
    /// Gets or sets number of children
    /// </summary>
    public int NumberOfChildren { get; set; }
}

连接字符串

连接字符串包含有关提供程序和数据源的信息。ACE OLDB 12.0 提供程序用于连接到 Access 数据库。此连接字符串会传递到数据访问代码中,以便 ADO.NET 对象可以与数据库建立连接。

存储连接字符串

通常,数据库连接字符串会存储在 CONFIG 文件中,以便于配置,并从中访问。要将连接字符串存储在配置文件中,请按照以下步骤操作:

  1. 右键单击“SocialClub.Desktop”项目,选择 添加 -> 新建项
  2. 在“添加新项”窗口中,选择 Visual C# 项 -> 常规 -> 应用程序配置文件,然后单击“确定” (app.config 将添加到项目中)。
  3. 在 app.config 中,添加以下代码
<configuration>
  <connectionStrings>
    <add name="SocialClubDBConnection"
        connectionString="Provider=Microsoft.ACE.OLEDB.12.0;
        Data Source=|DataDirectory|\SocialClub.accdb;Persist Security Info=True"
        providerName="System.Data.OleDb" />
  </connectionStrings>
</configuration>

访问连接字符串

ConfigurationManager 类提供对配置文件的访问。可以通过 ConfigurationManager 访问 app.config 中的连接字符串。在演示项目中,这是通过创建一个名为 ConnectionAccess 的抽象类来完成的,该类包含一个名为 ConnectionString 的属性,该属性返回存储在配置文件中的连接字符串。代码如下:

using System.Configuration;
/// <summary>
/// ConnectionAccess class
/// </summary>
public abstract class ConnectionAccess
{
    /// <summary>
    /// Gets connection string
    /// </summary>
    protected string ConnectionString
    {
        get 
        { 
            return ConfigurationManager
                .ConnectionStrings["SocialClubDBConnection"]
                .ToString(); 
        }
    }
}

为 MS Access 创建 SQL 语句

由于应用程序包含 CURD 操作,因此我们需要以下可以针对 Access 数据库执行的 SQL 语句:

  1. SELECT
  2. SELECT (按输入参数)
  3. INSERT
  4. 更新
  5. 删除

所有必需的 SQL 语句都已添加到一个静态类中,作为只读字符串并被访问。

类图

Data Model

代码:静态类中的 SQL 脚本

/// <summary>
/// DBConstants static class contains sql string constants
/// </summary>
public static class Scripts
{
    /// <summary>
    /// Sql to get a club member details by Id
    /// </summary>
    public static readonly string sqlGetClubMemberById = "Select" +
        " Id, Name, DateOfBirth, Occupation, MaritalStatus, " + 
        "HealthStatus, Salary, NumberOfChildren" +
        " From ClubMember Where Id = @Id";
    /// <summary>
    /// Sql to get all club members
    /// </summary>
    public static readonly string SqlGetAllClubMembers = "Select" +
        " Id, Name, DateOfBirth, Occupation, MaritalStatus, " + 
        "HealthStatus, Salary, NumberOfChildren" +
        " From ClubMember";
    /// <summary>
    /// sql to insert a club member details
    /// </summary>
    public static readonly string SqlInsertClubMember = "Insert Into" +
        " ClubMember(Name, DateOfBirth, Occupation," + 
        " MaritalStatus, HealthStatus, Salary, NumberOfChildren)" +
        " Values(@Name, @DateOfBirth, @Occupation, " + 
        "@MaritalStatus, @HealthStatus, @Salary, @NumberOfChildren)";
    /// <summary>
    /// sql to search for club members
    /// </summary>
    public static readonly string SqlSearchClubMembers = "Select " +
        " Id, Name, DateOfBirth, Occupation, MaritalStatus, " + 
        "HealthStatus, Salary, NumberOfChildren" +
        " From ClubMember Where (@Occupation Is NULL OR @Occupation = Occupation) {0}" +
        " (@MaritalStatus Is NULL OR @MaritalStatus = MaritalStatus)";
    /// <summary>
    /// sql to update club member details
    /// </summary>
    public static readonly string sqlUpdateClubMember = "Update ClubMember " +
        " Set [Name] = @Name, [DateOfBirth] = @DateOfBirth, " + 
        "[Occupation] = @Occupation, [MaritalStatus] = @MaritalStatus, " +
        " [HealthStatus] = @HealthStatus, [Salary] = @Salary, " + 
        "[NumberOfChildren] = @NumberOfChildren Where ([Id] = @Id)";
    /// <summary>
    /// sql to delete a club member record
    /// </summary>
    public static readonly string sqlDeleteClubMember = "Delete From ClubMember Where (Id = @Id)";
}

使用 ADO.NET 编写数据访问

ADO.NET 是 .NET Framework 附带的数据访问技术之一。它包含一组类,为 .NET 应用程序提供数据访问服务。我将带您了解 ADO.NET 对象的一些基础知识,这些对象用于数据库通信以及加载和修改数据的步骤。

ADO.NET 对象

连接对象

Connection 对象用于在应用程序和数据库之间创建连接。

命令对象

Command 对象用于存储需要针对数据库执行的 SQL 语句。Command 对象可以执行 SELECT、INSERT、UPDATE、DELETE、存储过程。

DataReader 对象

DataReader 对象用于从数据库检索数据。DataReader 对象是一种仅向前、只读的游标类型,它提供了一种更快地从数据库检索记录的方法。

DataAdapter 对象

DataAdapter 对象用于从数据库检索数据并将数据填充到 DataTableDataSet 中。DataSet 是数据库的内存表示,包含 DataTable 集合。DataAdapter 对象使用 Fill 方法将数据填充到 DataSet 中。它使用连接对象和命令对象自动打开连接、执行命令并关闭连接。

使用 DataAdapter 加载数据的步骤

  1. 创建 DataAdapter 对象的实例
  2. 将 Command 对象的新实例分配给 DataAdapter 的 SelectCommand 属性
  3. 设置 SelectCommand 的连接和 Command 属性
  4. 将 (任何) 参数添加到 SelectCommand 的 ParameterCollection
  5. 调用 DataAdapter 对象的 Fill 方法,并将 DataTable 对象传递给它。

使用这些 ADO.NET 对象取决于数据源。MS Access 是 OLE DB 数据源。连接到 OLEDB 数据源时,我们需要在 System.Data.OleDb 命名空间中使用 OleDbConnectionOleDdCommand

示例代码

// Create new instance of dataadapter object
OleDbDataAdapter oleDbDataAdapter = new OleDbDataAdapter()
// Create the command and set its properties
oleDbDataAdapter.SelectCommand = new OleDbCommand();
oleDbDataAdapter.SelectCommand.Connection = new OleDbConnection(this.ConnectionString);
oleDbDataAdapter.SelectCommand.CommandType = CommandType.Text;
// Assign the SQL to the command object
oleDbDataAdapter.SelectCommand.CommandText = Scripts.SqlGetAllClubMembers;
// Fill the datatable from adapter
oleDbDataAdapter.Fill(dataTable);

使用 Command 对象修改数据的步骤

  1. 创建一个新的 Command 对象实例
  2. 设置 Command 对象的连接属性
  3. 将 Command 对象的 CommandType 属性设置为 Text
  4. 通过设置 CommandText 属性将 SQL 语句放入 Command 对象中
  5. 将输入参数添加到 Command 对象的参数集合属性中
  6. 打开连接
  7. 通过调用命令对象上的 ExecuteNonQuery 方法来执行命令
  8. 关闭连接

示例代码

// Create a new instance of command object
OleDbCommand dbCommand = new OleDbCommand()
// Set the command object properties
dbCommand.Connection = new OleDbConnection(this.ConnectionString);
dbCommand.CommandType = CommandType.Text;
dbCommand.CommandText = Scripts.sqlUpdateClubMember;
// Add the input parameters to the parameter collection
dbCommand.Parameters.AddWithValue("@Name", clubMember.Name);
//..    
dbCommand.Parameters.AddWithValue("@Id", clubMember.Id);
// Open the connection, execute the query and close the connection
dbCommand.Connection.Open();
var rowsAffected = dbCommand.ExecuteNonQuery();
dbCommand.Connection.Close();

在将输入参数添加到参数集合时,请确保按照 SQL 语句中的顺序添加参数。

类图和数据访问代码

Data Access Class diagram

数据访问代码

using System;
using System.Data;
using System.Data.OleDb;
using John.SocialClub.Data.DataModel;
using John.SocialClub.Data.Sql;
/// <summary>
/// Data access class for ClubMember table
/// </summary>
public class ClubMemberAccess : ConnectionAccess, IClubMemberAccess
{
    /// <summary>
    /// Method to get all club members
    /// </summary>
    /// <returns>Data table</returns>
    public DataTable GetAllClubMembers()
    {
        DataTable dataTable = new DataTable();
        using (OleDbDataAdapter oleDbDataAdapter = new OleDbDataAdapter())
        {
            // Create the command and set its properties
            oleDbDataAdapter.SelectCommand = new OleDbCommand();
            oleDbDataAdapter.SelectCommand.Connection = new OleDbConnection(this.ConnectionString);
            oleDbDataAdapter.SelectCommand.CommandType = CommandType.Text;
            // Assign the SQL to the command object
            oleDbDataAdapter.SelectCommand.CommandText = Scripts.SqlGetAllClubMembers;
            // Fill the datatable from adapter
            oleDbDataAdapter.Fill(dataTable);
        }
        return dataTable;            
    }
    /// <summary>
    /// Method to get club member by Id
    /// </summary>
    /// <param name="id">member id</param>
    /// <returns>Data row</returns>
    public DataRow GetClubMemberById(int id)
    {
        DataTable dataTable = new DataTable();
        DataRow dataRow;
        using (OleDbDataAdapter dataAdapter = new OleDbDataAdapter())
        {
            // Create the command and set its properties
            dataAdapter.SelectCommand = new OleDbCommand();
            dataAdapter.SelectCommand.Connection = new OleDbConnection(this.ConnectionString);
            dataAdapter.SelectCommand.CommandType = CommandType.Text;
            dataAdapter.SelectCommand.CommandText = Scripts.sqlGetClubMemberById;
            // Add the parameter to the parameter collection
            dataAdapter.SelectCommand.Parameters.AddWithValue("@Id", id);
            // Fill the datatable From adapter
            dataAdapter.Fill(dataTable);
            // Get the datarow from the table
            dataRow = dataTable.Rows.Count > 0 ? dataTable.Rows[0] : null;
            return dataRow;
        }
    }
    /// <summary>
    /// Method to search club members by multiple parameters
    /// </summary>
    /// <param name="occupation">occupation value</param>
    /// <param name="maritalStatus">marital status</param>
    /// <param name="operand">AND OR operand</param>
    /// <returns>Data table</returns>
    public DataTable SearchClubMembers(object occupation, object maritalStatus, string operand)
    {
        DataTable dataTable = new DataTable();
        using (OleDbDataAdapter oleDbDataAdapter = new OleDbDataAdapter())
        {
            // Create the command and set its properties
            oleDbDataAdapter.SelectCommand = new OleDbCommand();
            oleDbDataAdapter.SelectCommand.Connection = 
                   new OleDbConnection(this.ConnectionString);
            oleDbDataAdapter.SelectCommand.CommandType = CommandType.Text;
            // Assign the SQL to the command object
            oleDbDataAdapter.SelectCommand.CommandText = 
              string.Format(Scripts.SqlSearchClubMembers, operand);
            // Add the input parameters to the parameter collection
            oleDbDataAdapter.SelectCommand.Parameters.AddWithValue(
                "@Occupation", 
                occupation == null ? DBNull.Value : occupation);
            oleDbDataAdapter.SelectCommand.Parameters.AddWithValue(
                "@MaritalStatus", 
                maritalStatus == null ? DBNull.Value : maritalStatus);
            // Fill the table from adapter
            oleDbDataAdapter.Fill(dataTable);
        }
        return dataTable;
    }        
    /// <summary>
    /// Method to add new member
    /// </summary>
    /// <param name="clubMember">club member model</param>
    /// <returns>true or false</returns>
    public bool AddClubMember(ClubMemberModel clubMember)
    {
        using (OleDbCommand oleDbCommand = new OleDbCommand())
        {
            // Set the command object properties
            oleDbCommand.Connection = new OleDbConnection(this.ConnectionString);
            oleDbCommand.CommandType = CommandType.Text;
            oleDbCommand.CommandText = Scripts.SqlInsertClubMember;
            // Add the input parameters to the parameter collection
            oleDbCommand.Parameters.AddWithValue("@Name", clubMember.Name);
            oleDbCommand.Parameters.AddWithValue("@DateOfBirth", 
                         clubMember.DateOfBirth.ToShortDateString());
            oleDbCommand.Parameters.AddWithValue("@Occupation", 
                        (int)clubMember.Occupation);
            oleDbCommand.Parameters.AddWithValue("@MaritalStatus", 
                        (int)clubMember.MaritalStatus);
            oleDbCommand.Parameters.AddWithValue("@HealthStatus", 
                        (int)clubMember.HealthStatus);
            oleDbCommand.Parameters.AddWithValue("@Salary", clubMember.Salary);
            oleDbCommand.Parameters.AddWithValue("@NumberOfChildren", 
                         clubMember.NumberOfChildren);
            // Open the connection, execute the query and close the connection
            oleDbCommand.Connection.Open();
            var rowsAffected = oleDbCommand.ExecuteNonQuery();
            oleDbCommand.Connection.Close();
            return rowsAffected > 0;
        }
    }
    /// <summary>
    /// Method to update club member
    /// </summary>
    /// <param name="clubMember">club member</param>
    /// <returns>true / false</returns>
    public bool UpdateClubMember(ClubMemberModel clubMember)
    {
        using (OleDbCommand dbCommand = new OleDbCommand())
        {
            // Set the command object properties
            dbCommand.Connection = new OleDbConnection(this.ConnectionString);
            dbCommand.CommandType = CommandType.Text;
            dbCommand.CommandText = Scripts.sqlUpdateClubMember;
            // Add the input parameters to the parameter collection
            dbCommand.Parameters.AddWithValue("@Name", clubMember.Name);
            dbCommand.Parameters.AddWithValue("@DateOfBirth", 
                      clubMember.DateOfBirth.ToShortDateString());
            dbCommand.Parameters.AddWithValue("@Occupation", 
                      (int)clubMember.Occupation);
            dbCommand.Parameters.AddWithValue("@MaritalStatus", 
                      (int)clubMember.MaritalStatus);
            dbCommand.Parameters.AddWithValue("@HealthStatus", 
                      (int)clubMember.HealthStatus);
            dbCommand.Parameters.AddWithValue("@Salary", clubMember.Salary);
            dbCommand.Parameters.AddWithValue("@NumberOfChildren", 
                      clubMember.NumberOfChildren);
            dbCommand.Parameters.AddWithValue("@Id", clubMember.Id);
            // Open the connection, execute the query and close the connection
            dbCommand.Connection.Open();
            var rowsAffected = dbCommand.ExecuteNonQuery();
            dbCommand.Connection.Close();
            return rowsAffected > 0;
        }
    }
    /// <summary>
    /// Method to delete a club member
    /// </summary>
    /// <param name="id">member id</param>
    /// <returns>true / false</returns>
    public bool DeleteClubMember(int id)
    {
        using (OleDbCommand dbCommand = new OleDbCommand())
        {
            // Set the command object properties
            dbCommand.Connection = new OleDbConnection(this.ConnectionString);
            dbCommand.CommandType = CommandType.Text;
            dbCommand.CommandText = Scripts.sqlDeleteClubMember;
            // Add the input parameter to the parameter collection
            dbCommand.Parameters.AddWithValue("@Id", id);
            // Open the connection, execute the query and close the connection
            dbCommand.Connection.Open();
            var rowsAffected = dbCommand.ExecuteNonQuery();
            dbCommand.Connection.Close();
            return rowsAffected > 0;
        }
    }
}

业务服务类

服务类充当数据访问和 UI 之间的桥梁。它包含调用数据访问方法的服务方法。

类图

Service class

代码:服务类

/// <summary>
/// Service class to query the DataAccess, implements IClubMemberService interface
/// </summary>
public class ClubMemberService : IClubMemberService
{
    /// <summary>
    /// interface of ClubMemberAccess
    /// </summary>
    private IClubMemberAccess memberAccess;
    /// <summary>
    /// Initializes a new instance of the ClubMemberService class
    /// </summary>
    public ClubMemberService()
    {
        this.memberAccess = new ClubMemberAccess();
    }
    /// <summary>
    /// Service method to get club member by Id
    /// </summary>
    /// <param name="id">member id</param>
    /// <returns>Data row</returns>
    public DataRow GetClubMemberById(int id)
    {
        // call to Data access method to get club member by id
        return this.memberAccess.GetClubMemberById(id);
    }
    /// <summary>
    /// Service method to get all club members
    /// </summary>
    /// <returns>Data table</returns>
    public DataTable GetAllClubMembers()
    {   
        // call to Data access method to get all club members         
        return this.memberAccess.GetAllClubMembers();
    }
    /// <summary>
    /// Service method to search records by multiple parameters
    /// </summary>
    /// <param name="occupation">occupation value</param>
    /// <param name="maritalStatus">marital status</param>
    /// <param name="operand">AND OR operand</param>
    /// <returns>Data table</returns>
    public DataTable SearchClubMembers(object occupation, object maritalStatus, string operand)
    {
        // Call to data access method with search parameters
        return this.memberAccess.SearchClubMembers(occupation, maritalStatus, operand);
    }
    /// <summary>
    /// Service method to create new member
    /// </summary>
    /// <param name="clubMember">club member model</param>
    /// <returns>true or false</returns>
    public bool RegisterClubMember(ClubMemberModel clubMember)
    {
        // Call to data access method to add club member details
        return this.memberAccess.AddClubMember(clubMember);
    }
    /// <summary>
    /// Service method to update club member
    /// </summary>
    /// <param name="clubMember">club member</param>
    /// <returns>true / false</returns>
    public bool UpdateClubMember(ClubMemberModel clubMember)
    {
        // Call to data access method to update club member details
        return this.memberAccess.UpdateClubMember(clubMember);
    }
    /// <summary>
    /// Method to delete a club member
    /// </summary>
    /// <param name="id">member id</param>
    /// <returns>true / false</returns>
    public bool DeleteClubMember(int id)
    {
        // Call to data access method to delete a member
        return this.memberAccess.DeleteClubMember(id);
    }
}

桌面:UI (窗体) 和事件

窗体是 WinForms 应用程序的基本单元。因此,设计用户界面的方式非常重要。.NET Framework 提供了丰富的控件来设计窗体,Visual Studio IDE 在设计窗体 (使用其拖放功能) 和编写控件事件代码方面提供了出色的支持。在演示项目中,我们有以下屏幕:

登录

一个简单的登录屏幕,包含控件 (标签、文本框和按钮),用于接受用户名和密码。按钮单击事件在代码隐藏中处理。凭据 (用户名、密码) 存储在设置中,通用消息、文本存储在资源文件中。在桌面项目中,展开“属性”节点,然后双击“设置/资源”以修改/检查详细信息。

Login Screen

登录示例代码:按钮单击事件

/// <summary>
/// Click event to handle the login process
/// </summary>
/// <param name="sender">sender object</param>
/// <param name="e">event data</param>
private void Login_Click(object sender, EventArgs e)
{
    if (txtUsername.Text.Trim() == Settings.Default.Username && 
            txtPassword.Text.Trim() == Settings.Default.Password)
    {
        var frmManage = new Manage();
        frmManage.Show();
        this.Hide();
    }
    else
    {
        MessageBox.Show(
            Resources.Login_Validation_Message,
            Resources.Login_Validation_Message_Title,
            MessageBoxButtons.OK,
            MessageBoxIcon.Information);
    }
}

注册

注册屏幕提供输入俱乐部成员信息的界面。屏幕截图和代码示例如下所示。

Registration

注册示例代码:按钮单击事件

/// <summary>
/// Click event to handle registration
/// </summary>
/// <param name="sender">sender object</param>
/// <param name="e">event data</param>
private void Register_Click(object sender, EventArgs e)
{
    try
    {
        // Check if the validation passes
        if (this.ValidateRegistration())
        {
            // Assign the values to the model
            ClubMemberModel clubMemberModel = new ClubMemberModel()
            {
                Id = 0,
                Name = txtName.Text.Trim(),
                DateOfBirth = dtDateOfBirth.Value,
                Occupation = (Occupation)cmbOccupation.SelectedValue,
                HealthStatus = (HealthStatus)cmbHealthStatus.SelectedValue,
                MaritalStatus = (MaritalStatus)cmbMaritalStatus.SelectedValue,
                Salary = txtSalary.Text.Trim() == 
                   string.Empty ? 0 : Convert.ToDecimal(txtSalary.Text),
                NumberOfChildren = txtNoOfChildren.Text.Trim() == 
                  string.Empty ? 0 : Convert.ToInt16(txtNoOfChildren.Text)
            };
            // Call the service method and assign the return status to variable
            var success = this.clubMemberService.RegisterClubMember(clubMemberModel);
            // if status of success variable is true then display
            // a information else display the error message
            if (success)
            {
                // display the message box
                MessageBox.Show(
                    Resources.Registration_Successful_Message,
                    Resources.Registration_Successful_Message_Title,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
                // Reset the screen
                this.ResetRegistration();
            }
            else
            {
                // display the error messge
                MessageBox.Show(
                    Resources.Registration_Error_Message,
                    Resources.Registration_Error_Message_Title,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }
        else
        {
            // Display the validation failed message
            MessageBox.Show(
                this.errorMessage, 
                Resources.Registration_Error_Message_Title, 
                MessageBoxButtons.OK, 
                MessageBoxIcon.Error);
        }
    }
    catch (Exception ex)
    {
        this.ShowErrorMessage(ex);
    }
}

搜索和管理

搜索和管理屏幕提供简单的搜索功能,并允许用户选择、更新、删除、打印和导出成员详细信息。一个轻量级类库“DataGridViewPrinter.dll”用于实现“打印”功能。该库取自此处。您可以参考该文章了解打印预览和打印功能是如何实现的。搜索和管理屏幕和一些示例代码如下所示。

Search & Manage

示例代码:搜索按钮单击事件

/// <summary>
/// Click event to handle search
/// </summary>
/// <param name="sender">sender object</param>
/// <param name="e">event data</param>
private void Search_Click(object sender, EventArgs e)
{
    try
    {
        // Call to service method by passing the selected search paramters
        DataTable data = this.clubMemberService.SearchClubMembers(
            cmbSearchOccupation.SelectedValue, 
            cmbSearchMaritalStatus.SelectedValue, 
            cmbOperand.GetItemText(cmbOperand.SelectedItem)
            );
        // Call to private method by passing the result set to load the grid view
        this.LoadDataGridView(data);
    }
    catch (Exception ex)
    {
        this.ShowErrorMessage(ex);
    }            
}
/// <summary>
/// Method to load data grid view
/// </summary>
/// <param name="data">data table</param>
private void LoadDataGridView(DataTable data)
{
    // Setting the data source and table for data grid view to display the data         
    dataGridViewMembers.DataSource = data;
    dataGridViewMembers.DataMember = data.TableName;
    dataGridViewMembers.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
}

结论

我介绍了使用 C# WinForms 连接到 MS Access、编写 ADO.NET 代码和应用 3 层模式的一些内容。希望您喜欢阅读本文。

参考文献

© . All rights reserved.