C#数据库教程7-ADO.NET三层架构和数据库DBNull问题
目录
一、数据库中创建表
1、创建数据表T_Person
列AiHao这种不确定的类型,可以为nvarchar(MAX)。
2、向数据表T_Person中插入数据
使用查询语句,向数据库中插入4条数据
insert into T_Person(Name,Age,AiHao,Height,BirthDay) values ('Pan',20,'BasketBall',130.00,'1995-09-16')
insert into T_Person(Name,Age,AiHao,Height,BirthDay) values ('Li',30,'FoottBall',110.09,'1985-11-12')
insert into T_Person(Name,Age,AiHao,Height,BirthDay) values ('Wang',40,'Swim',150.59,'1975-01-26')
insert into T_Person(Name,Age,Height,BirthDay) values ('Xu',32,119,'1989-01-02')
3、查看插入的数据
在数据表T_Person中右击编辑前200项,查看插入的四条数据
二、 创建C# Winform工程
1、添加引用
2、编辑数据库连接配置文件
App.config配置文件
3、添加封装的数据库类
添加前面章节中讲解所封装的SqlHelper类
三、添加具体业务功能代码
所谓三层架构一般描述为:表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)。本测试比较简单,将业务逻辑就放在UI中处理了。
1、创建三层架构
(1)创建UI窗口界面
UI层即界面层,这一层不出现任何数据库访问代码
(2)创建数据访问层DAL处理类
具体功能代码实现,后面具体展开
(3)创建Model
(Model不属于三层架构)
class PersonModel
{
//若在数据库中为可空类型,则C#中定义的数据类型后加?,string自带可空功能可不用添加,int则为int?
public long ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string AiHao { get; set; }
public decimal? Height { get; set; }
public DateTime? BirthDay { get; set; }
}
2、查询数据表中的数据总条数
(1)添加业务处理程序
/// <summary>
/// 获取数据总条数
/// </summary>
/// <returns></returns>
public static int GetCount()
{
return (int)SqlHelper.ExecuteScalar("select count(*) from T_Person");
}
(2)添加UI控件
(3)添加UI程序
private void btnDataCountGet_Click(object sender, EventArgs e)
{
int count = PersonDAL.GetCount();
txtDataCount.Text = count.ToString();
}
(4)运行
3、删除数据表中指定ID的数据
(1)添加业务处理程序
/// <summary>
/// 删除制定ID行数据
/// </summary>
/// <param name="ID"></param>
public static void DeleteByID(long ID)
{
SqlHelper.ExecuteNonQuery("delete from T_Person where ID=@ID",
new SqlParameter("@ID", ID));
}
(2)添加UI控件
(3)添加UI程序
private void btnDeleteData_Click(object sender, EventArgs e)
{
long row = int.Parse(txtDeleteRow.Text);
PersonDAL.DeleteByID(row);
MessageBox.Show("删除成功", "提示");
}
(4)运行
先删除指定的第四行,再查询发现数据总数居变成了3条,说明删除成功
查询数据库中,第四条数据已经删除
4、向数据库中插入数据
(1)添加业务处理程序
/// <summary>
/// 插入数据。
/// </summary>
public static void Insert(PersonModel person)
{
SqlHelper.ExecuteNonQuery("insert into T_Person(Name,Age,AiHao,Height,BirthDay) values (@_Name,@_Age,@_AiHao,@_Height,@_BirthDay)",
new SqlParameter("@_Name", person.Name),
new SqlParameter("@_Age", person.Age),
new SqlParameter("@_AiHao", person.AiHao),
new SqlParameter("@_Height", person.Height),
new SqlParameter("@_BirthDay", person.BirthDay)
);
}
(2)添加UI控件
(3)添加UI程序
private void btnInsert_Click(object sender, EventArgs e)
{
PersonModel person = new PersonModel();
person.Name = txtName.Text;
person.Age = Convert.ToInt32(txtAge.Text);
person.AiHao = txtAiHao.Text;
person.Height = Convert.ToDecimal(txtHeight.Text);
person.BirthDay = Convert.ToDateTime(txtBirthday.Text);
PersonDAL.Insert(person);
MessageBox.Show("插入成功", "提示");
}
(4)运行
数据库中查看
5、向数据库中插入Null的问题
(1)插入null
如数据库中的 ‘AiHao’列为可空项,将UI中的代码注释,设置断点运行
则在写数据时插入null代码异常,SqlHelper类中封装的SQL执行语句显示为缺少未输入参数
(2)解决方法
修改DAL中的代码,在插入数据库之前先判断该项若为null值、则先转换成数据库中的DBNull值类型。
/// <summary>
/// 插入数据。
/// </summary>
public static void Insert(PersonModel person)
{
object _aiHao;
if (person.AiHao==null)
{
_aiHao = DBNull.Value;
}
else
{
_aiHao = person.AiHao;
}
SqlHelper.ExecuteNonQuery("insert into T_Person(Name,Age,AiHao,Height,BirthDay) values (@_Name,@_Age,@_AiHao,@_Height,@_BirthDay)",
new SqlParameter("@_Name", person.Name),
new SqlParameter("@_Age", person.Age),
new SqlParameter("@_AiHao", _aiHao),
new SqlParameter("@_Height", person.Height),
new SqlParameter("@_BirthDay", person.BirthDay)
);
}
再次运行则发现成功写入
(3)封装该方法应用于其它几个可空的列
封装方法
/// <summary>
/// 抽象的方法:判断往数据库写的数据是否为null
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static object ToDBValue(object value)
{
if (value == null)
{
return DBNull.Value;
}
else
{
return value;
}
}
修改DAL的Insert方法
/// <summary>
/// 插入数据。
/// </summary>
public static void Insert(PersonModel person)
{
SqlHelper.ExecuteNonQuery("insert into T_Person(Name,Age,AiHao,Height,BirthDay) values (@_Name,@_Age,@_AiHao,@_Height,@_BirthDay)",
new SqlParameter("@_Name", person.Name),
new SqlParameter("@_Age", person.Age),
new SqlParameter("@_AiHao", ToDBValue(person.AiHao)),
new SqlParameter("@_Height", ToDBValue(person.Height)),
new SqlParameter("@_BirthDay", ToDBValue(person.BirthDay))
);
}
成功插入数据
6、读取指定ID号的数据
DAL中不要返回DataTable、DataRow等ADO.Net的类
(1)添加业务处理程序
读取的数据库表中的数据可能包含DBNull
/// <summary>
/// 读取数据表中指定ID的数据
/// </summary>
/// <param name="ID"></param>
/// <returns></returns>
public static PersonModel GetByID(long id)
{
DataTable table = SqlHelper.ExecuteDataTable("select * from T_Person where ID=@ID",
new SqlParameter("@ID", id));
if (table.Rows.Count <= 0)
{
return null; //不存在
}
else if (table.Rows.Count > 1)
{
//主键重复
throw new Exception("ID存在重复");
}
else
{
//DAL中不要返回DataTable、DataRow等ADO.Net的类
DataRow row = table.Rows[0];
PersonModel person = new PersonModel();
person.ID = (long)row["ID"];
person.Name = (string)row["Name"];
person.Age = (int)row["Age"];
if (row["AiHao"]==DBNull.Value)
{
person.AiHao = null;
}
else
{
person.AiHao = (string)row["AiHao"];
}
person.Height = (decimal?)row["Height"]; //可空类型
person.BirthDay = (DateTime?)row["BirthDay"]; //可空类型
return person;
}
(2)运行测试
UI按钮事件程序中设置断点测试,读取I数据表中,ID为8的数据
7、读取数据库值为DBNull的处理方法
(1)封装判断读取值是否为DBNull方法
/// <summary>
/// 抽象的方法,判断从数据库中读的数据是否为null。如果value这个数据库中的值为DBNull,则返回null
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static object FromDBValue(object value)
{
if(value==DBNull.Value)
{
return null;
}
else
{
return value;
}
}
(2)修改DAL中的GetByID程序
/// <summary>
/// 读取数据表中指定ID的数据
/// </summary>
/// <param name="ID"></param>
/// <returns></returns>
public static PersonModel GetByID(long id)
{
DataTable table = SqlHelper.ExecuteDataTable("select * from T_Person where ID=@ID",
new SqlParameter("@ID", id));
if (table.Rows.Count <= 0)
{
return null; //不存在
}
else if (table.Rows.Count > 1)
{
//主键重复
throw new Exception("ID存在重复");
}
else
{
//DAL中不要返回DataTable、DataRow等ADO.Net的类
DataRow row = table.Rows[0];
PersonModel person = new PersonModel();
person.ID = (long)row["ID"];
person.Name = (string)row["Name"];
person.Age = (int)row["Age"];
person.AiHao = (string)FromDBValue(row["AiHao"]); //string本身就是可空类型
person.Height = (decimal?)FromDBValue(row["Height"]); //可空类型
person.BirthDay = (DateTime?)FromDBValue(row["BirthDay"]); //可空类型
return person;
}
(3)添加UI控件
(4) 添加UI层按钮程序
private void btnRead_Click(object sender, EventArgs e)
{
long id = int.Parse(txtReadID.Text);
PersonModel person = PersonDAL.GetByID(id);
//txtReadID.Text = person.ID.ToString();
txtReadName.Text = person.Name;
txtReadAge.Text = person.Age.ToString();
txtReadHeight.Text = person.Height.ToString();
txtReadBirthDay.Text = person.BirthDay.ToString();
txtReadAiHao.Text = person.AiHao;
MessageBox.Show("读取成功", "提示");
}
(5)运行程序,读取
读取第3行
读取第8行
若有任何问题,欢迎私聊我。
工程下载
https://download.csdn.net/download/panjinliang066333/85439817
相关文章
- 你真的了解字典(Dictionary)吗? C# Memory Cache 踩坑记录 .net 泛型 结构化CSS设计思维 WinForm POST上传与后台接收 高效实用的.NET开源项目 .net 笔试面试总结(3) .net 笔试面试总结(2) 依赖注入 C# RSA 加密 C#与Java AES 加密解密
- 技术的正宗与野路子 c#, AOP动态代理实现动态权限控制(一) 探索基于.NET下实现一句话木马之asmx篇 asp.net core 系列 9 环境(Development、Staging 、Production)
- ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案 try.dot.net 的正确使用姿势 .Net NPOI 根据excel模板导出excel、直接生成excel .Net NPOI 上传excel文件、提交后台获取excel里的数据
- 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange
- C#订阅与发布标准实现 visual studio code .net 开发 设计模式之☞策略模式 C#字符串转二进制、二进制转字符串 c# 接口的协变和逆变 c# 使用迭代器来创建可枚举类型 博客园首页新随笔联系订阅管理 随笔 - 117 文章 - 0 评论 - 57 c# 创建,加载,修改XML文档
- C#面试题(转载) SQL Server 数据库基础笔记分享(下) SQL Server 数据库基础笔记分享(上) Asp.Net MVC4中的全局过滤器 C#语法——泛型的多种应用
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
- ASP.NET MVC深入浅出系列(持续更新) ORM系列之Entity FrameWork详解(持续更新) 第十六节:语法总结(3)(C#6.0和C#7.0新语法) 第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字 各种通讯连接方式 设计模式篇 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借
- ASP.NET MVC Filters 4种默认过滤器的使用【附示例】 数据库常见死锁原因及处理 .NET源码中的链表 多线程下C#如何保证线程安全? .net实现支付宝在线支付 彻头彻尾理解单例模式与多线程 App.Config详解及读写操作 判断客户端是iOS还是Android,判断是不是在微信浏览器打开
- [C#]使用 C# 代码实现拓扑排序 dotNet Core WEB程序使用 Nginx反向代理 C#里面获得应用程序的当前路径 关于Nginx设置端口号,在Asp.net 获取不到的,解决办法 .Net程序员 初学Ubuntu ,配置Nignix 夜深了,写了个JQuery的省市区三级级联效果
- C#设计模式总结 C#设计模式(22)——访问者模式(Vistor Pattern) C#设计模式总结 .NET Core launch.json 简介 利用Bootstrap Paginator插件和knockout.js完成分页功能 图片在线裁剪和图片上传总结 循序渐进学.Net Core Web Api开发系列【2】:利用Swagger调试WebApi
- 【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装 【手记】走近科学之为什么明明实现了IEnumerable<T>的类型却不能调用LINQ扩展方法 【手记】手机网页弹出层后屏蔽底层的滑动响应 【手记】ASP.NET提示“未能创建类型”处理 【Web】一个非常简单的移动web消息框 【手记】解决EXCEL跑SQL遇“查询无法运行或数据库表无法打开...”
- js_html_input中autocomplete="off"在chrom中失效的解决办法 使用JS模拟锚点跳转 js如何获取url参数 C#模拟httpwebrequest请求_向服务器模拟cookie发送 实习期学到的技术(一) LinqPad的变量比较功能 ASP.NET EF 使用LinqPad 快速学习Linq
- (六)Net Core项目使用Controller之一 c# log4net 不输出日志 .NET Standard库引用导致的FileNotFoundException探究 获取json串里的某个属性值 common.js 如何调用common.js js 筛选数据 Join 具体用法
- ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下
- Word控件Spire.Doc 【段落处理】教程(十七):在 C#、VB.NET 中的 Word 中按样式名称获取段落
- Word控件Spire.Doc 【超链接】教程(1):如何在C#/VB.NET中给Word 文档插入超链接
- Word控件Spire.Doc 【文档操作】教程(八):在 C#、VB.NET 中将内容从一个 Word 文档复制到另一个文档
- Word控件Spire.Doc 转换教程(二十):在 C#、VB.NET 中将 Word 转换为 Word XML
- c#.net SQL存储过程直接传表;用户定义表类型的表
- c# asp.net 编辑文件的摘要信息
- C#数据库教程1-使用ADO.NET操作sql server 2012
- C#使用 System.Net.Mail发送邮件功能
- 使用Microsoft Roslyn提取C#和VB.NET源代码中的字符串常量
- C#.Net下的防抖-Debounce和节流阀-Throttle功能实现
- C#与.NET Framework c#编程语言,和java是一样的。(c#,java) -->javaweb,asp.net