如何将 SQL 数据库连接到您的 C# 程序 - 初学者教程






4.75/5 (50投票s)
本文将向初学者介绍使用 C# 连接到 SQL Server 数据库的基本概念。
引言
本文旨在为初学者讲解 .NET Framework 中数据的基本概念,以及如何在应用程序中使用 SQL 客户端连接到数据库。
连接数据库所需的基本代码和命名空间,以及如何使用 C# 代码和应用程序在数据库上执行一组命令。
背景
作为一名 ASP.NET 开发人员,我一直很难学习如何使用 C# 连接数据库。使用 C# 创建连接到数据库对象的软件对我来说一直是个难题,我曾认为这是一件很困难的事情。
我学会了这一点,因此我想帮助新的开发人员学习如何使用应用程序中的 C# 代码将其应用程序连接到 SQL Server 数据库。
我将提供控制台应用程序的代码,因为控制台应用程序是 .NET Framework 中最简单的应用程序。WPF 和 Win Forms 也可以使用,但控制台应用程序对于此目的来说是一个不错的选择。以便您了解在此场景中代码的基本实现。
.NET Framework 中使用数据
.NET Framework 始终提供使用数据和代码中使用基本功能的基本实现。数据可以从某些文件中提取,也可以是应用程序中的数据,或者是来自数据库软件等。在 .NET 中,您可以使用 .NET Framework 提供的命名空间来处理它们。
OLEDB、SQL、LINQ 是此类工作的基本示例。在 SQL 中,您连接到数据库,我们将继续深入探讨数据库和 C# 代码。
但是,我们将使用的命名空间是 System.Data.SqlClient
,而不是 System.Data.Sql
。尽管第二个命名空间也与 SQL 相关函数一起使用,但 SqlClient 是我们在本场景中继续前进所需的命名空间。
System.Data.SqlClient
此 .NET Framework 程序集(命名空间)包含连接到数据库、读取/写入数据库数据所需的所有类。
错误和成功报告由它生成。SqlError
用于生成错误,成功代码将在屏幕上执行和显示。
我们将直接在此命名空间及其包含的类中使用我们的代码,以连接到数据库。执行命令以从中读取数据,或更新记录或一次性添加新记录。
使用 C# 处理 SQL Server
在此示例中,我将使用 SQL Server,因为我只安装了 SQL Server,所以我不太确定这是否适用于 MySQL 和 Oracle 等。但我很快就会将这部分内容添加到本文中。
连接到数据库
连接到数据库需要一个连接字符串。此字符串包含有关您要连接的服务器、您将需要的数据库以及您可用于连接的凭据的信息。每个数据库都有自己的属性、自己的服务器、名称和登录信息类型,通过这些信息您可以连接到数据库以从中读取/写入数据。
您可以从 Wikipedia 了解有关连接字符串的更多信息,正如他们所说:
引用在计算领域,连接字符串是一个指定有关数据源及其连接方式的信息的字符串。它在代码中传递给底层驱动程序或提供程序以启动连接。虽然常用于数据库连接,但数据源也可以是电子表格或文本文件。
从以上陈述可以轻松得出结论,连接字符串是有关数据源、数据以及连接到它的方法的基本信息。
http://www.connectionstrings.com/ 是您可以轻松找到数据库连接字符串的网站。它们为几乎所有数据库服务及其类型提供了字符串。一定要试试!在我提供的代码中,字符串是从该网站获取的,用于测试我自己的数据库。:)
在我谈到的命名空间中,SqlConnection
类为我们完成了这项工作。我们可以使用以下代码连接到 SQL 数据库:
using(SqlConnection conn = new SqlConnection()) { conn.ConnectionString = "Server=[server_name];Database=[database_name];Trusted_Connection=true"; // using the code here... }
这将创建一个与 SQL Server 数据库的新连接,该连接将使用提供的 ConnectionString 进行连接。您无需在系统上安装 SQL Server。因为我们已经说过 connectionString 只是一个字符串,用于告知底层代码数据软件提供商的位置和模式。所以我们甚至可以建立一个位于单独开发环境中的 SQL Server 连接。上面的连接字符串具有
- 服务器
字符串的这一部分告诉底层代码要连接的服务器名称。您的服务器名称会以这种方式有所不同。 - 数据库
这是您要连接的数据库的名称。
在所有数据库中,有两种登录方法:Windows 身份验证和数据库身份验证。在 Windows 身份验证中,数据库使用 Windows (OS) 的用户凭据进行身份验证;在数据库身份验证中,您需要提供用户名和密码才能连接到数据库。
在我的情况下,身份验证是 Windows,所以我不得不在字符串中写入 Trusted_Connection
部分。如果您使用数据库身份验证,则会在字符串中提供用户名和密码字段。
连接池
如前所述,连接数据库是一个打开连接、关闭连接等的漫长过程。为应用程序中的每个用户重复此过程不是一个好方法,它会减慢代码执行的速度。因此,在程序执行中,许多相同的连接会被打开、关闭、再打开。这些过程非常耗时,并且与良好的用户体验背道而驰。
.NET Framework ADO.NET 在此发挥作用,它通过创建我们所说的“连接池”来最小化打开和关闭过程,从而使程序执行速度稍快一些。此技术通过保存连接实例来减少打开连接的次数。对于每个新连接,它只查找已打开的连接,如果连接存在,则不尝试创建新连接;否则,它会根据连接字符串打开一个新连接。
请记住,只有配置相同的连接才能放入连接池。任何即使有一个细微差别的连接都需要为自己建立一个新的连接池。通常,它基于连接的 ConnectionString。您可以通过更改连接字符串中的值来了解它们会有何不同。
MSDN 文档中的一个例子是:
using (SqlConnection connection = new SqlConnection( "Integrated Security=SSPI;Initial Catalog=Northwind")) { connection.Open(); // Pool A is created. } using (SqlConnection connection = new SqlConnection( "Integrated Security=SSPI;Initial Catalog=pubs")) { connection.Open(); // Pool B is created because the connection strings differ. } using (SqlConnection connection = new SqlConnection( "Integrated Security=SSPI;Initial Catalog=Northwind")) { connection.Open(); // The connection string matches pool A. }
MSDN 关于连接池的文档 您可以从 MSDN 关于 SQL Server 连接池的文档中了解更多关于此主题的信息。
为什么在代码中使用“using
”
在 C# 中,有些对象会占用系统资源。需要移除、关闭、刷新和释放等。在 C# 中,您可以编写代码来创建一个资源的新实例,使用它,关闭它,刷新它,释放它。或者,另一方面,您也可以简单地使用 using
语句块,在该块中,创建的对象会被关闭、刷新和释放,然后资源就可以再次被其他进程使用。这确保了框架会为每个进程采取最佳措施。
我们可以通过简单的逐行代码来实现,例如:
SqlConnection conn = new SqlConnection(); conn.ConnectionString = "connection_string"; conn.Open(); // use the connection here conn.Close(); conn.Dipose(); // remember, there is no method to flush a connection.
这被最小化为:
using(SqlConnection conn = new SqlConnection()) { conn.ConnectionString = "connection_string"; conn.Open(); // use the connection here }
一旦代码跳出此块。资源将被自动关闭和释放。框架会以最佳方式进行处理。
执行命令
连接到数据库后,您可以执行您拥有的命令集,这些命令将在服务器(或数据提供程序)上执行,以执行您尝试执行的操作,例如查询数据、插入数据、更新记录等。
SQL 具有命令的基本语法,在我看来,它是编程世界中最简单的语法,并且接近人类可理解的命令。在该命名空间中,SqlCommand
类为我们完成了这项工作。命令的示例如下:
SqlCommand command = new SqlCommand("SELECT * FROM TableName", conn);
……SQL Server 上的每个命令都将如此执行:第一个参数是命令,第二个参数是命令将在其上执行的连接。您可以传递任何命令,底层代码会将其转换回将在数据所在的服务器上执行的命令,然后将结果返回给您,无论是错误还是成功报告。
有时您可能希望使用 INSERT INTO
子句的命令,要实现这一点,您需要向命令添加参数,以便您的数据库免受 SQL 注入的侵害。使用参数可以减少数据库被攻击的机会,如果用户尝试通过表单将某些命令添加到数据库服务器,它会抛出错误。
参数化数据
通过使用传递到命令的 SqlParameter
来参数化查询。例如,您可能想搜索条件匹配的记录。您可以通过将变量名传递到查询中,然后使用 SqlParameter
对象为其添加值来表示该条件。例如,以下是您要传递到服务器的 SqlCommand:
// Create the command SqlCommand command = new SqlCommand("SELECT * FROM TableName WHERE FirstColumn = @0", conn); // Add the parameters. command.Parameters.Add(new SqlParameter("0", 1));
在上面的代码中,添加的变量是 0,它的值也已传入。您可以使用任何变量,但它必须以 **@** 符号开头。完成此操作后,您可以将参数添加到该名称。在这种情况下,值 1 已硬编码,您也可以在此处添加变量值。
请记住,必须打开连接才能运行此代码,如果需要,您可以使用 conn.Open()
打开连接。
如代码中所述,我使用了数字(0)作为参数,它也可以是一个名称。例如,您也可以像这样编写代码:
// Create the command SqlCommand command = new SqlCommand("SELECT * FROM TableName WHERE FirstColumn = @firstColumnValue", conn); // Add the parameters. command.Parameters.Add(new SqlParameter("firstColumnValue", 1));
这样,您将更容易记住它们。我更擅长处理数字和索引,就像数组一样,所以我使用了 0,您可以使用名称、字母数字字符的组合等。只需将名称传递给 SqlParameter
对象即可!
读取返回的数据
在 SQL 中,您主要使用 SELECT 语句从数据库获取数据进行显示。CodeProject 会这样做以显示他们数据库中的最新文章,Google 会这样做以索引结果等。但是如何使用 C# 在应用程序中显示这些数据结果呢?这就是问题所在。嗯,在我们谈到的命名空间中,有一个名为 SqlDataReader
的类,它存在于 SqlCommand
中,它返回数据的 Reader 对象。您可以使用它来读取数据,并为每个列在屏幕上提供结果。
以下代码将在命令执行后获取结果:
// Create new SqlDataReader object and read data from the command. using (SqlDataReader reader = command.ExecuteReader()) { // while there is another record present while (reader.Read()) { // write the data on to the screen Console.WriteLine(String.Format("{0} \t | {1} \t | {2} \t | {3}", // call the objects from their index reader[0], reader[1], reader[2], reader[3])); } }
这是相同的代码,它将执行,一旦执行完成,它将让框架处理这项工作,并以最佳方式关闭资源。
向 SQL Server 添加数据
添加数据的实现方法类似。只有命令会改变,我们知道在数据库中,INSERT INTO
子句用于添加数据。所以,命令将变成:
SqlCommand insertCommand = new SqlCommand("INSERT INTO TableName (FirstColumn, SecondColumn, ThirdColumn, ForthColumn) VALUES (@0, @1, @2, @3)", conn);
然后您可以使用 SqlParameter
对象将值添加到参数中。这样,当命令执行时,数据将被添加到您指定的表中。
从 SQL Server 捕获错误
SQL Server 会生成错误供您捕获和处理。在我们正在使用的命名空间中,有两个类处理 SQL Server 抛出的错误和异常:
SqlError
SqlException
这些分别用于获取错误详细信息或捕获代码中的异常并打印数据结果。如果您将使用 try catch
块,那么您很可能会在代码中使用 SqlException
。
为了使其正常工作,我们将传递一个我们知道会引发错误的命令。
SqlCommand errorCommand = new SqlCommand("SELECT * FROM someErrorColumn", conn);
现在我们知道这是有缺陷的,但直到我们执行它,它都不会生成任何错误。为了做到这一点,我们将尝试像这样执行它:
errorCommand.ExecuteNonQuery();
一旦执行此操作,SQL Server 就会抱怨说不存在该表。要捕获它,您可以使用带有 SqlException
的 try catch 块在 catch 块中捕获。对于工作的代码,您可以在我文章的实时示例中看到以下代码块。它解释了此处 SqlException
的 try catch 块的用法。
工作示例
文章中有一个示例可供下载,如果您需要进行操作。
您需要使用 SQL Server、数据库和表来确保程序正常工作。如果服务器名称、数据库名称或表不匹配,程序将无法运行。示例中没有办法附加数据库。因为数据库需要 SQL Server 数据库,它将始终可通过连接访问。我将不再使用此数据库,因此我没有提供数据库连接字符串。
数据库表
我系统中的数据库表如下:
SELECT 而不带 WHERE
您可以运行控制台,您将在屏幕上看到结果。这是 SELECT
查询运行的代码,并且返回的列的输出被打印出来:
带 WHERE 的 SELECT
同时,我们可以向 SELECT
查询添加一些参数,以便只提取我们想要的数据。例如,如果我们向 SELECT
查询添加一个 WHERE
子句,将生成以下结果:
插入数据
完成之后,您可以进入下一步。这一部分与第二个命令有关,我们在其中将记录添加到表中。此语句一旦执行,数据就会被添加到表中,现在的表如下:
这是当上述代码在我们的应用程序中使用时会发生什么的示例。我还会写出在此控制台应用程序中使用的代码。代码块中添加了注释,以便您了解代码的工作原理。
源代码
using System; using System.Data; using System.Data.SqlClient; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SqlTest_CSharp { class Program { static void Main(string[] args) { // Create the connection to the resource! // This is the connection, that is established and // will be available throughout this block. using (SqlConnection conn = new SqlConnection()) { // Create the connectionString // Trusted_Connection is used to denote the connection uses Windows Authentication conn.ConnectionString = "Server=[server_name];Database=[database_name];Trusted_Connection=true"; conn.Open(); // Create the command SqlCommand command = new SqlCommand("SELECT * FROM TableName WHERE FirstColumn = @0", conn); // Add the parameters. command.Parameters.Add(new SqlParameter("0", 1)); /* Get the rows and display on the screen! * This section of the code has the basic code * that will display the content from the Database Table * on the screen using an SqlDataReader. */ using (SqlDataReader reader = command.ExecuteReader()) { Console.WriteLine("FirstColumn\tSecond Column\t\tThird Column\t\tForth Column\t"); while (reader.Read()) { Console.WriteLine(String.Format("{0} \t | {1} \t | {2} \t | {3}", reader[0], reader[1], reader[2], reader[3])); } } Console.WriteLine("Data displayed! Now press enter to move to the next section!"); Console.ReadLine(); Console.Clear(); /* Above code was used to display the data from the Database table! * This following section explains the key features to use * to add the data to the table. This is an example of another * SQL Command (INSERT INTO), this will teach the usage of parameters and connection.*/ Console.WriteLine("INSERT INTO command"); // Create the command, to insert the data into the Table! // this is a simple INSERT INTO command! SqlCommand insertCommand = new SqlCommand("INSERT INTO TableName (FirstColumn, SecondColumn, ThirdColumn, ForthColumn) VALUES (@0, @1, @2, @3)", conn); // In the command, there are some parameters denoted by @, you can // change their value on a condition, in my code they're hardcoded. insertCommand.Parameters.Add(new SqlParameter("0", 10)); insertCommand.Parameters.Add(new SqlParameter("1", "Test Column")); insertCommand.Parameters.Add(new SqlParameter("2", DateTime.Now)); insertCommand.Parameters.Add(new SqlParameter("3", false)); // Execute the command, and print the values of the columns affected through // the command executed. Console.WriteLine("Commands executed! Total rows affected are " + insertCommand.ExecuteNonQuery()); Console.WriteLine("Done! Press enter to move to the next step"); Console.ReadLine(); Console.Clear(); /* In this section there is an example of the Exception case * Thrown by the SQL Server, that is provided by SqlException * Using that class object, we can get the error thrown by SQL Server. * In my code, I am simply displaying the error! */ Console.WriteLine("Now the error trial!"); // try block try { // Create the command to execute! With the wrong name of the table (Depends on your Database tables) SqlCommand errorCommand = new SqlCommand("SELECT * FROM someErrorColumn", conn); // Execute the command, here the error will pop up! // But since we're catching the code block's errors, it will be displayed inside the console. errorCommand.ExecuteNonQuery(); } // catch block catch (SqlException er) { // Since there is no such column as someErrorColumn (Depends on your Database tables) // SQL Server will throw an error. Console.WriteLine("There was an error reported by SQL Server, " + er.Message); } } // Final step, close the resources flush dispose them. ReadLine to prevent the console from closing. Console.ReadLine(); } } }
上面的代码是此应用程序运行所使用的源代码。
关注点
SQL Server 不需要您在机器上安装 SQL Server。您可以连接到位于独立环境中的 SQL Server 实例,但您需要确保连接已建立,并且您可以连接到提供数据的服务器。数据库可以位于不同的位置,唯一能将它们连接起来的是正确的连接字符串。
连接字符串必须准确,以便服务器可以提供确切的数据。
重要提示:此处提供的表和数据库架构与我拥有的数据库和表相关。您屏幕上的结果可能会(肯定会)有所不同。此处引发的结果和错误可能与您的系统不同。这只是一个示例!它取决于数据库表及其数据和属性。
历史
第一篇文章。