SQL Server 使用C#窗体与数据库连接,制作数据库查看器
SQL Server 使用C#窗体与数据库连接,制作数据库查看器
本文中心:讨论C#对SQL Server 的增删改查,使用Treeview制作数据库查看器。
- SSMS部分:确保SQL Server 提供 SQL身份验证,同时建立一个对 名为 test 的数据库有操作权限的用户(用户名:pc,密码:123456)
--建表,插入数据 use test; create table [User_Info]( [ID] int not null primary key, [Username] varchar(20) not null, [Password] varchar(10) not null ); create table [Blog]( [ID] int not null primary key check([ID]>0), [Title] varchar(100) not null, [Content] varchar(100), [Author_Id] int references [User_Info]([ID]) ); insert into [User_Info] values(001,'Kevin Li','123456'); insert into [User_Info] values(002,'Donold','123456'); insert into [User_Info] values(003,'Ki','123456'); insert into [User_Info] values(004,'Steves','123456'); insert into [User_Info] values(005,'Bill','123456'); insert into [User_Info] values(006,'Jaf','123456'); insert into [User_Info] values(007,'An Li','123456'); insert into [Blog] values(01,'Build Your Dreams','Read and Action',005); select * from User_Info; select * from Blog;
- C#部分:VS2022新建一个窗体应用,项目名称:”SQLServerConnection“
- V层:主窗体Form1布局以及修改属性如下:
- form1
- 事件 Load=Form1_Load
- 属性 StartPosition=CenterScreen
- 属性 FormBorderStyle = FixedSingle
- 属性 Text = SQLServer数据库查看器
- 属性 MaximizeBox = False
- treeView1
- 事件 AfterSelect = treeView1_AfterSelect
- listView1
- 属性 FullRowSelect = True
- 属性 GridLines = True
- 属性 View = Details
- form1
-
M层:新建数据库连接类 DB.cs。
相当于M层的角色,采用了单例的思想编写,确保数据库不会被多次连接占用系统的资源.C#对SQL Server的查询过程为:先打开数据库,查询,关闭数据库连接。只是查出来的结果,C#直接放到 **SqlDataAdapter **中,再直接 Fill 方法填充到 DataTable 里面。
这里主要提供两个方法,一是 getBySql 提供查询使用,即从SQL Server 查询数据使用;二是 setBySql 用作写数据。上述两个方法提供不同参数的重载,主要是用于应对带参数与不带参数的查询。
这里采用
string.format("{0}{1}",new Object[]{"a","b"});
将a,b分别替换{0}与{1}的位置,防止任何形式的SQL注入。如补加 and 1 or 1在后面最后会形成 where xx = 'and 1 or 1'。同时由于C#规定不能在构造函数中关闭连接,这里只能实现 IDisposable 的接口。
在本程序中没用到写。
using System; using System.Collections.Generic; using System.Data; //DataTable 用到 using System.Data.SqlClient; //一系列的数据库操作类用到 using System.Text; namespace SQLServerConnection { class DB : IDisposable { private SqlConnection sqlConnection; //以下代码保证该类只能有一个实例 //在自己内部定义自己的一个实例,只供内部调用 private static DB db = null; //这个类必须自动向整个系统提供这个实例对象 //这里提供一个供外部访问本class 的静态方法,可以直接访问 public static DB GetInstance() { if (db == null) { db = new DB(); } return db; } //私有无参构造函数 public DB() { sqlConnection = new SqlConnection("server=.;uid=pc;pwd=123456;database=test"); sqlConnection.Open(); } //单例化结束 //查询 public DataTable GetBySql(String sql, Object[] param) { sql = String.Format(sql, param);//用字符串参数替换的形式防止注入 SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(new SqlCommand(sql, sqlConnection)); DataTable dataTable = new DataTable(); sqlDataAdapter.Fill(dataTable); return dataTable; } //无参数的查询 public DataTable GetBySql(String sql) { SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(new SqlCommand(sql, sqlConnection)); DataTable dataTable = new DataTable(); sqlDataAdapter.Fill(dataTable); return dataTable; } //无查询结果的修改 public void setBySql(string sql, Object[] param) { sql = String.Format(sql, param);//用字符串参数替换的形式防止注入 new SqlCommand(sql, sqlConnection).ExecuteNonQuery(); } //无参数,无查询结果的修改 public void setBySql(string sql) { new SqlCommand(sql, sqlConnection).ExecuteNonQuery(); } //相当于析构函数 public void Dispose() { sqlConnection.Close(); //在C#中关闭数据库连接不能在类的析构函数中关闭,否则会抛出“内部.NET Framework 数据提供程序错误 1”的异常 //通过实现C#中 IDisposable 接口中的 Dispose() 方法主要用途是释放非托管资源 } } }
- C层:Form1.cs,承担将数据库的查询结果与其他组件连接起来的角色。主要使用了TreeView,对其节点TreeNode的操作,节点名同样是Text,在节点下添加节点用父节点Nodes.Add(子节点)。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace SQLServerConnection { public partial class Form1 : Form { DB db; public Form1() { InitializeComponent(); } //选择树节点触发 private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { //删除根节点,点击根节点是没有任何动作的! if (e.Node.Parent != null) { string table_name = e.Node.Text; groupBox2.Text = "表" + table_name; listView1.Clear(); //查表的信息 DataTable table_info = db.GetBySql("select name from syscolumns where id=object_id('{0}')", new Object[] { table_name }); for (int i = 0; i < table_info.Rows.Count; i++) { for (int j = 0; j < table_info.Columns.Count; j++) { //生成表头 listView1.Columns.Add(table_info.Rows[i][j] + "", listView1.Width / table_info.Rows.Count - 1, HorizontalAlignment.Left); } } //查表的内容 DataTable table = db.GetBySql("select * from [{0}]", new Object[] { table_name }); //数据更新,UI暂时挂起,知道EndUpdate绘制控件,可以有效避免闪烁并大大提高加载速度 listView1.BeginUpdate(); for (int i = 0; i < table.Rows.Count; i++) { ListViewItem listViewItem = new ListViewItem();//生成每一列 for (int j = 0; j < table.Columns.Count; j++) { if (j <= 0) { listViewItem.Text = table.Rows[i][j] + ""; } else { listViewItem.SubItems.Add(table.Rows[i][j] + ""); } } listView1.Items.Add(listViewItem); } //结束数据处理,UI界面一次性绘制。 listView1.EndUpdate(); } } private void Form1_Load(object sender, EventArgs e) { try { TreeNode root_node = new TreeNode();//建立节点 root_node.Text = "Test 数据库"; treeView1.Nodes.Add(root_node); db = DB.GetInstance();//初始化数据库查询单例 DB.cs //查询test数据库有多少张表 DataTable table_name = db.GetBySql("select name from sysobjects where(xtype = 'U')"); //遍历查询出来的结果表(视图) for (int i = 0; i < table_name.Rows.Count; i++) { for (int j = 0; j < table_name.Columns.Count; j++) { TreeNode treeNode = new TreeNode(); treeNode.Text = table_name.Rows[i][j] + ""; //一一将查询结果也就是表名添加到树节点 root_node.Nodes.Add(treeNode); } } } catch { MessageBox.Show(this.Text, "数据库出错!"); Environment.Exit(1); } } } }
- 效果
解决方案含有的目录:
DB.cs 是数据库连接类
Form1.cs 是主窗体
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统