【发布时间】:2021-10-17 13:00:52
【问题描述】:
主题: 模拟数据库管理系统的数据结构和算法 要求:
- 数据存储
- 查询:支持选择、插入、更新查询
我打算在winform上做,有创建表,选择,删除,更新命令,就像sql一样。但我不知道如何用 C# 编写这些函数。有人有关于 SQL 基本功能的文档吗?请帮我。 任何了解该主题的人都可以逐步指导我吗?我真的不知道该怎么办
【问题讨论】:
标签: c# winforms data-structures
主题: 模拟数据库管理系统的数据结构和算法 要求:
我打算在winform上做,有创建表,选择,删除,更新命令,就像sql一样。但我不知道如何用 C# 编写这些函数。有人有关于 SQL 基本功能的文档吗?请帮我。 任何了解该主题的人都可以逐步指导我吗?我真的不知道该怎么办
【问题讨论】:
标签: c# winforms data-structures
在现代编程中,倾向于将数据(= 模型)与数据的显示方式(= 视图)分开。要将视图连接到模型,我们需要一个适配器类:viewmodel。这三个类一起缩写为 MVVM。考虑阅读有关此的内容。
将模型和视图分离的好处是,可以将模型重用于其他视图,可以改变模型而不改变视图,或者改变视图而不改变模型。最后,无需表单就可以更轻松地对模型类进行单元测试。
我提到 MVVM,因为您尝试将数据库处理与 WinForms 混合。数据库处理(模型)与您如何显示获取的数据无关。
回到你的问题
显然,显示获取的数据(目前)没有问题。因此,让我们关注如何在 C# 中获取数据库数据。
有两种主要方法:一种是使用 SQL,通过 DbConnection 和 DbCommand。另一种常用的方法是使用实体框架和 LINQ。
您提到您已经拥有用于获取数据的 SQL。因此,我将专注于该方法。如果您对实体框架感兴趣,请考虑阅读Entity Framework Code First 并在电视上没有任何内容时做一些实验。
您需要一种方法来创建表。由于表是一起工作的,我的建议是不要创建一个创建一个表的方法,而是创建一个在一次调用中创建数据库的所有表的方法。
public void CreateAllTables()
{
const string sqlText = "Create if not exists TableCustomers (
Id int,
FirstName Varchar(30),
...
确切的语法在一定程度上取决于您使用的 SQL 方言:MicroSoft? mysql?简单的 SQL?好吧,我想你比我更了解 Sql 文本。关于如何发送这个数据库:
using (var dbConnection = new DbConnection())
{
using (DbCommand dbCommand = dbConnection.CreateCommand())
{
dbCommand.CommandText = sqlText;
现在有几种方法可以执行 dbCommand:
DbCommand.ExecuteReader
DbCommand.ExecuteScalar
DbCommand.ExecuteNonQuery
在这种情况下:我们只执行命令。在与数据库通信之前,我们必须打开 dbConnection:
dbConnection.Open();
dbCommand.ExecuteNonQuery();
}
}
}
DbCommand.ExecuteNonQuery 有一个返回值:受影响的行数。有时检查一下是否发生错误可能会很方便。
现在来获取一些数据
public IEnumerable<Product> FetchStudentsByLastName(string lastName)
{
const string sqlText = "Select Id, FirstName, LastName, ...
From tableStudents
Where LastName = @LastName;"
请注意,我的 SQL 有 @LastName 作为参数!
开头和CreateTables中的一样:
using (var dbConnection = new DbConnection())
{
using (DbCommand dbCommand = dbConnection.CreateCommand())
{
dbCommand.CommandText = sqlText;
填写参数:
// associate the parameter in the SQL text with the value:
dbCommand.AddWithValue("@LastName", lastName);
现在我们准备打开 dbConnection 并执行查询。我们希望获取几行,所以我们必须使用DbCommand.ExecuteReader:
dbConnection.Open();
using (DbDataReader dbReader = dbCommand.ExecuteReader())
{
dbDataReader 包含获取的数据。使用DbDataReader.Read 找出是否还有要读取的行。如果是这样,请使用GetInt32、GetString 等读取每一行中的单元格:
while (dbReader.Read())
{
显然有一排。我们选择 Id 作为第 0 列,FirstName 作为第 1 列,LastName 作为第 2 列,等等:
Student fetchedStudent = new Student
{
Id = dbReader.GetInt32(0), // column 0 is an Int32
FirstName = dbReader.GetString(1), // column 1 is a string
LastName = dbReader.GetString(2),
...
}
yield return fetchedStudent;
}
}
}
}
要添加一个学生,我们做了类似的事情:创建 DbConnection 和 DbCommand。使用 SQL 文本和 AddWithParameter 填充 DbCommand。
不同的是:我们不希望返回多行,我们只想要添加的学生的Id。
如何在命令中返回 Id 取决于您使用的 SQL 方言。在 SQLLight 中会是这样的:
const string sqlText = "INSERT INTO tableStudent (
FirstName, LastName, ...) Values(@FirstName, @LastName, ...);
SELECT last_insert_rowid();"
添加新学生后,此 SQL 文本将返回学生的 Id。
创建 DbConnection 和 DbCommand。那么:
dbCommand.CommandText = sqlText;
dbCommand.AddWithValue("@FirstName, firstName);
dbCommand.AddWithValue("@LastName, lastName);
...
打开数据库,执行查询,只有一个结果:ExecuteScalar,返回返回的Id为int:
dbConnection.Open();
return (int)dbCommand.ExecuteScalar();
我已经向您展示了如何使用 DbConnection 和 DbCommand 与数据库进行通信。
我展示了如何向 SQL 文本添加参数。
要获取数据行使用ExecuteReader 和逐行读取,使用DbReader.Read 和DbReader.GetString(colum number) 等。
我展示了如何在不返回值的情况下执行:DbCommand.ExecuteNonQuery。用于创建表、删除表、更新表中的行、删除表中的行。
最后,我展示了如何返回一个值:DbCommand.ExecuteScalar。用于添加新行时返回Id。
【讨论】: