Winform 三层架构小例子
http://www.cnblogs.com/jacky73/archive/2009/09/01/1558083.html
在web开发中常常用到工厂模式三层架构,现在也在Winform中应用这种架构方式,尝试了很多,也模仿了经典例子PetShop,但是还是不行,也参考了网上的一些例子。现在把我这个例子的整个制作过程简单的介绍一下。(由于本例子是介绍三层结构,所以只是简单的应用,如果你觉得这种方式好,请自己实现其他模块)
结构:
-------PMIS--------主程序代码
表示层,负责应用程序的表现形式、用户体验等。
-------DALFactory-----抽象工厂
抽象工厂,用于创建各种数据对象的方法,这里有配置文件和反射的运用。
-------IDAL--------数据接口层(控制是选择什么类型的数据库)
数据操作接口,数据访问层实现其接口并重写它(体现了面向接口的编程思想)。
-------BLL------
处理应用程序的业务逻辑,被表示层调用。
-------Model-------构造模型(对应数据库字段)
Model程序集,存放实体类,用于数据访问层和逻辑层调用
-------SQLServerDAL----SQLServer数据访问层
数据访问层,实现具体的select、update、delete....操作,重写IDAL接口。
-------DBUtility----公共数据访问层
数据处理层,实现具体的ExecuteReader,ExecuteDataTable,ExecuteNonQuery等。
-------Utility----公共层
实现从配置文件中读取数据库联接字符串。
1、数据库结构
数据库名PMIS
表Admin
[ID] [bigint] 编号
[Name] [varchar](10) 名称
[PassWord] [varchar](100) 密码
略......
建表语句
CREATE TABLE [dbo].[Admin](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Name] [varchar](10) COLLATE Chinese_PRC_CI_AS NOT NULL,
[PassWord] [varchar](100) COLLATE Chinese_PRC_CI_AS NOT NULL,
[PurviewID] [int] NOT NULL,
[Remember] [int] NULL,
[AutoRun] [int] NULL,
[DepartmentsID] [bigint] NULL,
CONSTRAINT [PK_管理员_1] PRIMARY KEY CLUSTERED
(
[ID] ASC
) ON [PRIMARY]
) ON [PRIMARY]
2、接着建立数据库模型
Model
#region 内部成员字段
private int _id;
private string _Name;
private string _Password;
略...
#endregion
#region 方法
public AdminInfo() { }
public AdminInfo(string userName, string password)
{
this._Name = userName;
this._Password = password;
}
#endregion
3、建立DALFactory-----抽象工厂
public static IDAL.IAdmin Create()
{
string path=System.Configuration.ConfigurationSettings.AppSettings["DAL"];
string className="SQLServerDAL.Admin";
IDAL.IAdmin acount=(IDAL.IAdmin)Assembly.Load(path).CreateInstance(className);
return acount;
}
4、建立IDAL--------数据接口层
public interface IAdmin
{
AdminInfo Login(string userName, string password);
int Insert(AdminInfo account);
int Update(AdminInfo account);
}
5、建立Utility----公共层
public static string ConnectionString()
{
return (ConfigurationSettings.AppSettings["ConnectionString"]);
}
6、建立DBUtility----公共数据访问层和SQLServer数据访问层
DBUtility中建立SQLHelper类
SQLServerDAL的Admin类需要继承IAdmin
public class Admin:IAdmin
{}
Admin类主要实现用户登陆功能
7、建立业务逻辑曾BLL
方法public static AdminInfo Login(string userName, string password){}
8、为PMIS主程序添加应用程序配置文件app.config
添加<appSettings>
<add key="ConnectionString" value="server=.;uid=sa;pwd=;database=PMIS"></add>
<add key="DAL" value="SQLServerDAL"></add>
</appSettings>
在主程序的窗体中添加控件,为按钮添加事件
if (BLL.Admin.Login(参数) == null)
{
//处理...
}
else
{
//处理...
}
========
C# 使用三层架构实例演示-winForm 窗体登录功能
http://blog.csdn.net/qq649792393/article/details/41450193
什么是三层架构?百度百科讲的很详细,大家可以去搜索。这篇文章并不是讨论这个问题。而是通过一个例子帮助大家理解三层。理论上的东西讲的比较少。希望可以帮助到像我这样的小白学习。希望可以帮助到大家!
个人觉得这个例子还是很基础的,但是也可以帮助大家理解三层的设计理念。完成了这个小例子之后,你可以轻松的创建拥有相同功能的asp页面,而不需要更改太多的代码,因为代码处理的逻辑与数据操作已经实现了,只需更改网页空间属性及调用方法即可,同时帮助了解分层的便利性。至于三层的缺陷,大家可以在以后的开发中慢慢了解。
好了废话不说了,下面我们就直接开始正文吧。
数据库设计相当简单,就一个数据库然后又张存着用户名和密码的表。
数据库设计:
数据库名称:threeLayer
表: users
列:1.username 账号 2.password 密码
数据库创建表的脚本如下:
[sql] view plain copy
CREATE TABLE [dbo].[users](
[id] [int] IDENTITY(1,1) NOT NULL,
[username] [varchar](50) NULL,
[password] [varchar](50) NULL,
CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [dbo].[users] ON
INSERT [dbo].[users] ([id], [username], [password]) VALUES (1, N'admin', N'admin')
INSERT [dbo].[users] ([id], [username], [password]) VALUES (2, N'user1', N'user1')
INSERT [dbo].[users] ([id], [username], [password]) VALUES (3, N'user2', N'user2')
INSERT [dbo].[users] ([id], [username], [password]) VALUES (4, N'user3', N'user3')
SET IDENTITY_INSERT [dbo].[users] OFF
三层数据传递整体思路:
用户输入账号密码->点击登录->进入BLL层进行输入与数据的逻辑处理->进入DAL层将BAL层的逻辑进行实现(用户输入的账号的密码与数据库匹配),返回结果
其中数据的传递用model实体类属性来传递
步骤:
新建一个windows 窗体应用程序项目并命名为threeLayerText,路径自己选吧,可以选择回收站
在自动新建的窗体项目中,双击Form1.cs,打开窗体设计。
在窗体中添加两个label,两个TextBox分别命名为textBoxAccount、textBoxtextBoxPsw和一个button 命名
为 butLogin。这里命名指的是控件name属性
为窗体添加一个应用配置文件:右键窗体项目文件-添加-新建项-应用程序配置文件
在配置文件<configuration>节点中添加数据库连接语句
根据数据库配置Initial Catalog 为数据库名称,User ID 为登录数据库账户,Password 为改账号密码
添加后app.config完整内容如下
[html] view plain copy
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="dbConnection" connectionString="Data Source=.;Initial Catalog=threeLayer;Persist Security Info=True;User ID=sa;Password=123"
providerName="SQLClient" />
</connectionStrings>
</configuration>
添加类库:右键项目解决方案-添加-新建项目-类库,命名,确定
分别添加DAL、BAL、Model三个类库
在Model类库中添加userInfo类,用于在各个层之间传递数据
在类库中新建一个用户类 userInfo:右键Model类库-添加-类(或者选中model类库,使用shift+alt+c快捷键)
在userInfo类中添加属性
[csharp] view plain copy
private string _username;
private string _psw;
public string username
{
set { _username = value; }
get { return _username; }
}
public string psw
{
set { _psw = value; }
get { return _psw; }
}
Model类完整代码如下:
[csharp] view plain copy
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Model
{
public class userInfo
{
private string _username;
private string _psw;
public string username
{
set { _username = value; }
get { return _username; }
}
public string psw
{
set { _psw = value; }
get { return _psw; }
}
}
}
在DAL层中添加数据连接、查询操作类和方法
添加system.configuration引用,使类可以读取配置文件节点,读取配置文件中连接数据库语句;右键引用-添加引用-选择程序集-勾选-确定
添加 DBbase类(右键DAL项目-添加-新建项-命名好-确定) 用于连接数据库,添加System.Data 和 System.Data.SqlClient 命名空间,别问我用来干吗,其实我也不知道用来干吗的。
创建一个基本的查询方法用于查询并返回记录条数。DBbase类完整代码如下:
[csharp] view plain copy
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace DAL
{
public class DBbase
{
//读取配置文件 连接数据库语句
public static string strCon = System.Configuration.ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString;
//public static string strCon = "Data Source=.;Initial Catalog=threeLayer;Persist Security Info=True;User ID=sa;Password=123";
//实例化连接对象 con
SqlConnection con = new SqlConnection(strCon);
//检测连接是否打开
public void chkConnection()
{
if (this.con.State == ConnectionState.Closed)
{
this.con.Open();
}
}
//执行语句,返回该语句查询的数据行的总数
public int returnRowCount(string strSQL)
{
chkConnection();
try
{
SqlDataAdapter da = new SqlDataAdapter(strSQL, con);
DataSet ds = new DataSet();
da.Fill(ds);
return ds.Tables[0].Rows.Count;
}
catch
{
return 0;
}
}
}
}
添加 userAccess类(右键DAL项目-添加-新建项-命名好-确定) 用执行查询语句查找用户输入账号密码在数据库中存在记录条数
userAccess类完整代码如下:
[csharp] view plain copy
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DAL
{
public class userAccess
{
//实例化DBbase 对象
DBbase db = new DBbase();
//用户登录的方法
public int userLogin(string name, string psw)
{
string strsql = "select * from users where username = '" + name + "' and password = '" + psw + "'";
return db.returnRowCount(strsql);
}
}
}
在BLL层中添加用户输入数据与数据库匹配的逻辑代码
添加Model、DAL类库引用:右键BLL类库中引用文件夹,右键-添加引用-选择解决方案-项目-选中Model、DAL-确定
实例化DAL.userAccess 类,并新建一个方法调用DAL.userAccess方法,参数为Model实体类中的useInfo类,完整代码如下:
[csharp] view plain copy
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BLL
{
public class userAccess
{
DAL.userAccess d_userAccess = new DAL.userAccess();
public int userLogin(Model.userInfo m_userInfo)
{
return d_userAccess.userLogin(m_userInfo.username, m_userInfo.psw);
}
}
}
回到窗体设计中,添加用户输入处理与调用BLL层方法
添加Model、DAL类库引用:右键threeLayerText项目中引用文件夹,右键-添加引用-选择解决方案-项目-选中Model、BLL-确定
打开窗体后台代码,实例化Model.userInfo 、BLL.userAccess。代码如下
[csharp] view plain copy
//实例化model层中 userInfo类用于传递数据
Model.userInfo m_userInfo = new Model.userInfo();
//实例化BLL层中 userAccess方法衔接用户输入与数据库匹配
BLL.userAccess b_userAccess = new BLL.userAccess();
双击登录按钮,添加点击事件。代码如下
[csharp] view plain copy
//将用户输入的账号密码 赋值给userInfo类 username、psw属性
m_userInfo.username = textBoxAccount.Text.Trim().ToString();
m_userInfo.psw = textBoxPsw.Text.Trim().ToString();
//如果BLL层中 useLogin调用返回记录条数 大于1 则账号密码正确
if (b_userAccess.userLogin(m_userInfo) > 0)
{
MessageBox.Show("登录成功");
}
else
{
MessageBox.Show("登录失败");
}
完整Form1.cs 代码如下
[csharp] view plain copy
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace threeLayerText
{
public partial class Form1 : Form
{
//实例化model层中 userInfo类用于传递数据
Model.userInfo m_userInfo = new Model.userInfo();
//实例化BLL层中 userAccess方法衔接用户输入与数据库匹配
BLL.userAccess b_userAccess = new BLL.userAccess();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
//登录按钮 事件
private void butLogin_Click(object sender, EventArgs e)
{
//将用户输入的账号密码 赋值给userInfo类 username、psw属性
m_userInfo.username = textBoxAccount.Text.Trim().ToString();
m_userInfo.psw = textBoxPsw.Text.Trim().ToString();
//如果BLL层中 useLogin调用返回记录条数 大于1 则账号密码正确
if (b_userAccess.userLogin(m_userInfo) > 0)
{
MessageBox.Show("登录成功");
}
else
{
MessageBox.Show("登录失败");
}
}
}
}
保存,可以调试了。
关于Model实体层的描述:
Model又叫实体类,这个东西,大家可能觉得不好分层。我是这样理解的:UI<-->Model<-->BLL<-->Model<-->DAL,如此则认为Model在各层之间起到了一个数据传输的桥梁作用。不过在这里,我们不是把事情想简单,而是想复杂了。
摘自:http://www.cnblogs.com/sdjxcolin/archive/2008/12/12/1353780.html 这篇文章讲解了这个问题
========
C#中三层架构UI、BLL、DAL、Model实际操作
http://blog.csdn.net/zhgl7688/article/details/43669463
三层架构分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)再加上实体类库(Model)
1、实体类库(Model),主要存放数据库中的表字段。
操作:
(1)先建立实体类库Model,打开项目,在解决方案中右键--》添加--》新建项目--》选中类库--》改名Model--》确定
(2)选中Model类库--》Shift+ALT+C--》建立实体类。UserInfo类
[csharp] view plain copy 在CODE上查看代码片派生到我的代码片
namespace Model
{
public class UserInfo
{
public string UserName { get; set; }
public string Password { get; set; }
}
}
2、数据访问层(DAL),主要是存放对数据类的访问,即对数据库的添加、删除、修改、更新等基本操作
操作:
(1)先建立数据访问层类库DAL,打开项目,在解决方案中右键--》添加--》新建项目--》选中类库--》改名DAL--》确定
(2)在DAL中添加对Model的引用,选中DAL--》Alt+P+R--》解决方案--》项目--》选中MOdel--》确定
(3)在DAL中添加对system.configuration的引用,选中DAL--》Alt+P+R--》程序集--》框架--》选中System.configuration--》确定
(4)建立数据访问类,选中DAL--》Shift+ALT+C--》建立数据访问类。UserDB类
[csharp] view plain copy 在CODE上查看代码片派生到我的代码片
using System.Configuration;
using Model;
using System.Data;
using System.Data.SqlClient;
namespace DAL
{
class UserDB
{
private string connString = ConfigurationManager.ConnectionStrings["connString"].ToString();
public int AddUser(UserInfo userInfo)
{
//对数据库进添加一个用户操作
string commandText = "insert into UserInfo (userName,Password)values(@userName,@Password)";
SqlParameter[] paras = new SqlParameter[]
{
new SqlParameter ("@userName",userInfo.UserName ),
new SqlParameter ("@Password",userInfo.Password )
};
return SqlHelper.ExecuteNonQuery(connString, CommandType.Text, commandText, paras);
}
}
[csharp] view plain copy 在CODE上查看代码片派生到我的代码片
//添加其他对数据库操作
}
3、业务逻辑层(BLL)对传送数据进行逻辑判断分折,并进行传送正确的值。
(1)先建立业务逻辑层类库BLL,打开项目,在解决方案中右键--》添加--》新建项目--》选中类库--》改名BLL--》确定
(2)在BLL中添加对Model、DAL的引用,选中BLL--》Alt+P+R--》解决方案--》项目--》选中MOdel、DAL--》确定
(3)建立业务逻辑类,选中BLL--》Shift+ALT+C--》建立业务逻辑类。LoginManager类
[csharp] view plain copy 在CODE上查看代码片派生到我的代码片
using DAL;
using Model;
namespace BLL
{
public class LoginManager
{
private UserDB userDB = new UserDB();
public bool Add(UserInfo userInfo, out string messageStr)
{
messageStr = "";//返回界面层添加用户返回信息
bool isSuccess = false;
if (userInfo.UserName.Trim().Length != 0)//判断从传递来的username是否为空
{
if (userDB.IsEquals(userInfo))//传给DALl操作判断数据库中是否有重复值
{
userDB.AddUser(userInfo);//传给DAL操作增加一个新用户
isSuccess = true;
}
else
messageStr = "有相同的值";
}
else
{
messageStr = "不能为空";
}
return isSuccess;//返回界面层是否添加成功
}
}
}
5、表现层(UI)即用户界面层
(1)在UI中添加对Model、BLL的引用,选中UI--》Alt+P+R--》解决方案--》项目--》选中MOdel、BLL--》确定
(2)编写代码传递数据给BLL层。
[csharp] view plain copy 在CODE上查看代码片派生到我的代码片
UserInfo userInfo;
LoginManager lm = new LoginManager();
private void btnAdd_Click(object sender, EventArgs e)
{
userInfo = new UserInfo()
{
UserName = txtUserName.Text.Trim(),
Password = txtPassword.Text.Trim()
};
string messageStr = "";
if (lm.Add(userInfo, out messageStr))
{
MessageBox.Show("添加成功");
}
else
{
MessageBox.Show(messageStr);
txtUserName.Focus();
}
}
}
========
用三层架构来做winform程序
http://blog.csdn.net/clb929/article/details/54295211
三层架构是一种代码分层思想,简单的说就是将一个项目分为界面展示、业务逻辑、数据访问三层,各层之间保持一定的独立性,降低代码之间的耦合性,这样做的好处是显而易见的:
1、各层之间的改动不会影响到其他层(比较大的变动除外,如果客户要求业务流程、数据库结构都变了,你还期望有什么不会变呢)
2、基本不用写SQL语句了,自动生成的代码是参数化查询,可以防止SQL注入
3、代码条理清楚,便于理解
当然三层架构不是拯救一切的灵丹妙药,比如:
1、比较小的项目何必纠结用什么架构呢,在你琢磨架构的时候,用winform可能已经写完了
2、速度会有所降低,相对于直接访问数据库,三层架构增加了中间层,速度降低是肯定的
说到三层架构,可能第一时间想到的就是mvc,然而三层架构并不是web的专利,归根结底,三层架构只是一种代码分层思想,winform当然也可以用,只不过界面展示这块,mvc是网页的形式,winform是windows窗体,其他两层思路是一样的。
下面就以一个非常简单常见的商铺展示程序来实际讲解winform中如何实现三层架构。
一、前期准备
1、动软代码生成器,国产神器,你值得拥有,全自动生成数据访问层代码,百度就能找到,最后一版是2.78,作者没有继续更新了。已经免费开源,喜欢研究源代码的可以继续扩展。
李天平的博客
http://blog.csdn.net/litp
http://www.cnblogs.com/ltp/category/44293.html
2、SQLiteStudio,选择SQLite数据库是因为轻巧、无需安装,对于这个示例程序足够用了 ,SQLiteStudio是免费好用的SQLite数据库图形化管理工具,百度可得绿色版。
二、开发过程
1、下载动软代码生成器,安装完成之后运行,连接到附件示例程序的SQLite数据库,打开连接,右键点击数据库,选择“新建.net项目”,选择“简单三层结构”,下一步,选择“Shops”、“Users”两个表,点击“开始生成”。
2、来到生成目录,打开源代码,可以看到5个项目,下面分别说说他们的作用
BLL--业务逻辑层,所有的业务逻辑全部写在这里,动软已经为每个表自动生成了一个业务类,类名就是表名,BasicMethod区段是自动生成的一些基础方法,比如增删改查、分页查询这些,ExtensionMethod区段是空的,我们自己写的业务代码写在这个区段。
DAL--数据访问层,所有的数据库访问的基础方法写在这里,动软已经为每个表自动生成了一个数据访问类,类名就是表名,BasicMethod区段是自动生成的一些基础方法,比如增删改查、分页查询这些,ExtensionMethod区段是空的,如果我们觉得这些基础的数据库操作方法不够用,可以在这个区段添加自己的数据库操作方法,但是只有数据库的操作方法应该写在DAL类库。
DBUtility--数据库访问的基础类库,封装了MySQL,Sql,OLE,SqlLite,Oracle等数据库访问的方法,与ADO.NET相关的connection,DataAdapter,Command等全部在这里,DAL是在DBUtility基础上的进一步封装的,这个类库基本不需要修改。
Model--数据库表结构的映射,每一个类名代表数据库中的一个相同名字的表,类的每一个字段、属性表示表中对应的字段,数据库的一条记录就对应类的一个对象,这个类库基本不需要修改。
Web-- 一些基础的网页,因为我们是做winform的,所以这个不需要了,但是先别急着删,等下我们还要来拷连接字符串。
最后在解决方案文件夹下有一个Lib文件夹,是一些动态链接库,看看上述每个项目缺什么就引用什么。
3、新建一个winform项目,在项目的属性里将目标框架设置为".net framework 4"(不是".net framework 4 profile"),这样就有一个app.config文件了,打开app.config,打开Web项目根目录下的Web.config文件,将appSettings整个一节拷贝到app.config文件configuration节点内,将连接字符串修改为SqlLite的格式,删除Web项目。
补充一点,我们的程序是怎么得到连接字符串的呢?在DBUtility类库里,有一个PubConstant类,里面有一个ConnectionString属性,通过ConfigurationManager.AppSettings["ConnectionString"]读取了app.config文件里保存的连接字符串。
接下来就是开始做界面,写代码了,winform相信大家都很熟悉了,具体过程我就不多说了,直接上源代码。
示例程序源代码:
http://pan.baidu.com/s/1jIRZkfO
总结:
1、动软自带的SQLite动态链接库比较老,用他原来的运行不起来,我换成了新版的,在Lib文件夹下的SQLite.Interop.dll和System.Data.SQLite.DLL,System.Data.SQLite.DLL需要在项目中引用,SQLite.Interop.dll要手动拷贝到生成目录
2、如果代码写完后数据库结构发生了变化(比如增加了一个字段),我能想到的办法就是重新用动软生成一次,将BLL,DAL,DBUtility,Model替换掉,所以最好这几个项目中不要写自己的代码了,要扩展的话重新建项目吧。为什么不推荐手动改呢,因为即便是增加一个字段,也可能涉及到几个类的修改,改动大就更不用说了,手动改代码的话很有可能漏掉,能用最简单的办法搞定的事就用最简单的办法。
========