图片 1图片 2

三层架构(3-tier architecture)          

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace Entery
 7 {
 8     public class People
 9     {
10         private string name;
11         private string password;
12 
13         public string Name
14         {
15             get { return name; }
16             set { name = value; }
17         }
18 
19         public string Password
20         {
21             get { return password; }
22             set { password = value; }
23         }
24 
25         public People()
26         { 
27         
28         }
29         public People( string name,string password)
30         {
31             this.name = name;
32             this.password = password;
33         }
34     }
35 }

例:对表 users 建立查询,添加操作类

图片 3图片 4

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace ConsoleApplication2.App_Code
{
    public class UsersData
    {
        SqlConnection conn = null; //“公海” 提升 conn cmd 的作用域
        SqlCommand cmd = null;

        public UsersData()    //构造函数,放置每个方法都要使用,每次实例化都要运行
        {
            string sql = "server=.;database=Data0216;user=sa;pwd=123";

            conn = new SqlConnection(sql);
            cmd = conn.CreateCommand();
        }

        //查询所有方法

        public List<Users> SelectAll()    //有返回值 List<Users> 返回一个集合,
        {
            List<Users> list = new List<Users>();  //实例化一个 集合

            cmd.CommandText = "select *from Users";  //查询语句

            conn.Open();

            SqlDataReader dr = cmd.ExecuteReader();

            while (dr.Read())  //在这里没有进行有无 行 的判断,直接读取记录  
            {                                         

                Users u = new Users();  //实例化一个 users 对象,前提是已经建立 users 实体类

                u.Ids = Convert.ToInt32(dr["ids"]);
                u.UserName = dr["UserName"].ToString();
                u.PassWord = dr["PassWord"].ToString();
                u.NickName = dr["NickName"].ToString();
                u.Sex = Convert.ToBoolean(dr["Sex"]);
                u.Birthday = Convert.ToDateTime(dr["Birthday"]);
                u.Nation = dr["Nation"].ToString();

                list.Add(u);        
            }
            conn.Close();

            return list;   //返回 list 
        }


        //添加记录方法
        public void Insert(Users u)  //需要输入,输入一个 users 类型的变量
        {
            cmd.CommandText = "insert into Users values(@username,@password,@nickname,@sex,@birthday,@nation)";

            cmd.Parameters.Clear();
            cmd.Parameters.AddWithValue("@username", u.UserName);
            cmd.Parameters.AddWithValue("@password", u.PassWord);
            cmd.Parameters.AddWithValue("@nickname", u.NickName);
            cmd.Parameters.AddWithValue("@sex", u.Sex);
            cmd.Parameters.AddWithValue("@birthday", u.Birthday);
            cmd.Parameters.AddWithValue("@nation", u.Nation);

            conn.Open();
            cmd.ExecuteNonQuery();
            conn.Close();
        }

    }
}

View Code

 

现在注册一个用户然后看看显示的效果。

                            数据访问类

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Data.SqlClient;
 5 using System.Data;
 6 using System.Text;
 7 
 8 namespace DAL
 9 {
10     public static class SQLServerDALHelper
11     {
12         //integrated security=true 的意思是集成验证,也就是说使用Windows验证的方式去连接到数据库服务器。
13         public static string Consql = @"Data Source=PC-201610212048;Initial Catalog=People_Data_System;Integrated Security=True";
14 
15         public static bool ExecuteNonQuery(string sql)
16         {
17             try
18             {
19                 using (SqlConnection conn = new SqlConnection(Consql))
20                 {
21                     conn.Open();//打开数据库
22 
23                    using( SqlCommand com = new SqlCommand(sql, conn)){
24                     return com.ExecuteNonQuery() > 0;
25                        //通过cmd对象对数据库进行操作,执行非查询
26                    }
27                 }
28             }
29             catch
30             {
31                 throw;
32             }
33         }
34 
35         public static Object ExecuteScalar(string sql)
36         {
37             try
38             {
39                 using (SqlConnection conn = new SqlConnection(Consql))
40                 {
41                     conn.Open();//打开数据库
42 
43                     using( SqlCommand com = new SqlCommand(sql, conn))
44                     {
45                         return com.ExecuteScalar();
46                     }
47                 }
48             }
49             catch
50             {
51                 throw;
52             }
53         }
54 
55         public static SqlDataReader GetDataReader(string sql)
56         {
57             try
58             {
59                 SqlConnection conn = new SqlConnection(Consql);
60 
61                 conn.Open();
62 
63                 using (SqlCommand com = new SqlCommand(sql, conn))
64                 {
65                     return com.ExecuteReader(CommandBehavior.CloseConnection);
66                 }
67             }
68             catch
69             {
70                 throw;
71             }
72         }
73     }
74 }

缺点

1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。

2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。

3、增加了开发成本。

 

*** 约定  在项目下建文件夹 App_Code
 要创建的实体类文件,操作类文件都放在改文件夹下。

                  实体类文件名=表明,操作类文件名=表名+Data

 

  实体类
  

        — 数据库映射出来的结构对象,最简单的封装。

 

把数据库的表名变成类的类名

把数据库的每一个列,变为实体类中的成员变量和属性

列名与属性名一致

 

图片 5图片 6

优点

1、开发人员可以只关注整个结构中的其中某一层;

2、可以很容易的用新的实现来替换原有层次的实现;

3、可以降低层与层之间的依赖;

4、有利于标准化;

5、利于各层逻辑的复用。

6、结构更加的明确

7、在后期维护的时候,极大地降低了维护成本和维护时间

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using Entery;
 5 using System.Data.SqlClient;
 6 using System.Text;
 7 
 8 namespace DAL
 9 {
10      public class PeopleDAL
11     {
12          public bool Insert(People p)
13          {
14              return SQLServerDALHelper.ExecuteNonQuery(
15                  "insert into Users(Name,Pass) values('"
16                 + p.Name
17                 + "','"
18                 + p.Password
19                 + "')");
20          }
21          public bool Delete(People p) {
22              return SQLServerDALHelper.ExecuteNonQuery(
23                  "delete from Users"
24                 + " where Name = '"
25                 + p.Name
26                 + "'"
27                  );
28          }
29 
30          public bool Select(People p) {
31              return SQLServerDALHelper.ExecuteScalar(
32                  "select Pass from Users where Name = '"
33                  + p.Name
34                  + "'").ToString() == p.Password;                
35          }
36          /// <summary>
37          /// 返回数据集
38          /// </summary>
39          /// <returns></returns>
40          public List<People> SelectAll()
41          {
42              return ConvertReaderToTicketList(SQLServerDALHelper.GetDataReader(
43                     "select * from Users"
44                  )
45              );
46          }
47 
48          public static List<People> ConvertReaderToTicketList(SqlDataReader dr)
49          {
50              List<People> ts = new List<People>();
51 
52              if (dr.HasRows)
53              {
54                  while (dr.Read())
55                  {
56                      ts.Add(new People(dr[0].ToString(), dr[1].ToString()));
57                  }
58              }
59 
60              return ts;
61          }
62     }
63 }

练习题

对 Student表,重新排序 。如当 S002 删除后剩下的重新排序
S001     S001
S003     S002
S004     S003

 

 解一,只在C#端

图片 7图片 8

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            int max = 0;

            string sql = "server=.;database=Data0216;user=sa;pwd=123";
            SqlConnection conn = new SqlConnection(sql);
            SqlCommand cmd = conn.CreateCommand();

            //查询总数
            cmd.CommandText = "select COUNT(*) from Students";

            conn.Open();

            SqlDataReader dr = cmd.ExecuteReader();

            dr.Read();
            // max 共有多少条记录
            max = Convert.ToInt32(dr[0]);

            conn.Close();

            conn.Open();

            //将编号从1到 max 变为s001~s00max
            for (int i = 0; i < max; i++)
            {
                string newcode = "S" + (i + 1).ToString("000");


                cmd.CommandText = "update Students set Scode='" + newcode + "' where ids = (select top 1 ids from Students where Ids not in(select top " + i + " ids from Students)) ";



                cmd.ExecuteNonQuery();
            }
            conn.Close();

            Console.WriteLine("成功了!");

            Console.ReadLine();
        }
    }
}

View Code

select  top 1  *  from  student ; 

                                      —— 查询全部取第一行

select  top  2  *  from  student ; 

                                     —— 查询全部取前两行

select  top 1 * from student  where  ids  not  in (  select  top 1
 ids  from  student   )

                                      —— 查询第二行  括号内1变为 2
取第三行

 

解 二 

1、student 实体类

图片 9图片 10

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2.App_Code
{
    public class Students
    {
        private int _Ids;

        public int Ids
        {
            get { return _Ids; }
            set { _Ids = value; }
        }
        private string _Scode;

        public string Scode
        {
            get { return _Scode; }
            set { _Scode = value; }
        }
        private string _Sname;

        public string Sname
        {
            get { return _Sname; }
            set { _Sname = value; }
        }


    }
}

student 实体类

 

2、student 方法类

图片 11图片 12

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;

namespace ConsoleApplication2.App_Code
{
    public class StudentsData
    {
        SqlConnection conn = null;
        SqlCommand cmd = null;

        public StudentsData()
        {
            conn = new SqlConnection("server=.;database=Data0216;user=sa;pwd=123");
            cmd = conn.CreateCommand();
        }

        public void ResetNumber()//没有返回值的操作类
        {
            List<Students> slist = new List<Students>();//返回一个泛型集合

            cmd.CommandText = "select *from Students";

            conn.Open();

            SqlDataReader dr = cmd.ExecuteReader();

            while (dr.Read())
            {
                Students s = new Students();//实例化一个 Student 对象

                s.Ids = Convert.ToInt32(dr["Ids"]);
                s.Scode = dr["Scode"].ToString();
                s.Sname = dr["Sname"].ToString();

                slist.Add(s);//接受
            }
            conn.Close();

            int count = 1;

            //遍历,更改所有的编号
            foreach (Students sss in slist)
            {
                sss.Scode = "S" + count.ToString("000");
                count++;
            }

            conn.Open();

            //将改好的编号添加进去
            foreach (Students ss in slist)
            {
                cmd.CommandText = "Update Students set Scode=@a where Ids = @b";
                cmd.Parameters.Clear();
                cmd.Parameters.AddWithValue("@a", ss.Scode);
                cmd.Parameters.AddWithValue("@b", ss.Ids);
                cmd.ExecuteNonQuery();
            }
            conn.Close();

        }

    }
}

student 操作类

 

3、 整合调用

图片 13图片 14

using System.Text;
using ConsoleApplication2.App_Code;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            StudentsData st = new StudentsData();
            st.ResetNumber();

           // 可简化写为  new StudentsData().ResetNumber();

            Console.ReadKey();
        }
    }
}

min 接口操作

 

 

 

 1 public string Id
 2         {
 3             get;
 4             set;
 5         }
 6 public People( string id,string name,string password)
 7         {
 8             this.id = id;
 9             this.name = name;
10             this.password = password;
11         }

     数据访问层(Data access
layer)主要是对非原始数据(数据库或者文本文件等存放数据的形式)的操作层

下面我们就来用三层结构实现用户登录:

认识分层结构,分层式结构是最常见,也是最重要的一种结构。

这里我添加了一个构造函数,对于可能需要实现的功能来说,重载构造函数就多了一种实现方法,所以不管有用没用,先写上再说。

 

我们在写完业务逻辑层之后就要考虑表现层的问题了,为了将增删改查都在一个页面上表现出来,WinForm这样设计

     数据访问层包括   实体类

只这样修改还是不行的,因为我们在查询方法上还有错误,接着在修改一下DAL层

     界面层(User Interface layer)
主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。

图片 15所需控件,lable textbox
button dataGridView。

 

图片 16图片 17

例:对表 users 实体类封装

图片 18图片 19

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2.App_Code
{
    public class Users
    {
        private int _Ids;

        public int Ids
        {
            get { return _Ids; }
            set { _Ids = value; }
        }
        private string _UserName;

        public string UserName
        {
            get { return _UserName; }
            set { _UserName = value; }
        }
        private string _PassWord;

        public string PassWord
        {
            get { return _PassWord; }
            set { _PassWord = value; }
        }
        private string _NickName;

        public string NickName
        {
            get { return _NickName; }
            set { _NickName = value; }
        }
        private bool _Sex;

        public bool Sex
        {
            get { return _Sex; }
            set { _Sex = value; }
        }
        private DateTime _Birthday;

        public DateTime Birthday
        {
            get { return _Birthday; }
            set { _Birthday = value; }
        }
        private string _Nation;

        public string Nation
        {
            get { return _Nation; }
            set { _Nation = value; }
        }

    }
}

View Code

 

 

 
数据访问类(操作类)  

 

                —
将某个表的数据库操作写成一个一个方法,放入到此类中供外部调用

 

创建数据库我就不详细介绍了,只贴出代码就好了

     业务逻辑层(Business Logic
Layer)主要是针对具体的问题的操作,也可以理解成对数据层的操作

 1  private void button1_Click(object sender, EventArgs e)
 2         {
 3             try
 4             {
 5                 //新建一个类,这里使用无参的构造函数,方便以后反射
 6                 People p = new People();
 7 
 8                 //为它的属性赋值
 9                 p.Name = textBox1.Text.ToString();
10                 p.Password = textBox2.Text.ToString();
11                 
12                 //调用bll的添加业务
13                 string message = bll.Sel(p) ? "登陆成功" : "登陆失败";
14 
15                 MessageBox.Show(message);
16             }
17             catch
18             {
19                 throw;
20                 //如果出错,可能是数据转换出错或者数据库里已经存在相同的票号
21                // MessageBox.Show("输入数据形式错误,或主键重复");
22             }
23         }

View Code

首先注册一个admin
密码也为admin,用来测试登陆和删除,然后实现dataGridView显示所有数据。

接着我们开始要实现登陆问题了。代码如下:

 

图片 20图片 21

登陆代码实现之后就是删除数据的实现了,

图片 22图片 23为什么dataGridView会显示这个样子呢?为什么添加的中文用户名会出现??这个符号呢?大家有没有遇到过这种情况

View Code

图片 24图片 25

1  public bool Insert(People p)
2          {
3              return SQLServerDALHelper.ExecuteNonQuery(
4                  "insert into Users(Name,Pass) values(N'"
5                 + p.Name
6                 + "',N'"
7                 + p.Password
8                 + "')");
9          }

View Code

 1 private void button3_Click(object sender, EventArgs e)
 2         {
 3             try
 4             {
 5                 //新建一个类,这里使用无参的构造函数,方便以后反射
 6                 People p = new People();
 7 
 8                 //为它的属性赋值
 9                 p.Name = textBox1.Text.ToString();
10 
11                 //调用bll的添加业务
12                 string message = bll.Del(p) ? "删除成功" : "删除失败";
13 
14                 MessageBox.Show(message);
15             }
16             catch
17             {
18                 throw;
19             }
20         }

 

 1 这里先自定义一个shows()方法,然后在Form_Load里调用shows()方法 
 2 private void shows()
 3         {
 4             try
 5             {
 6                 dataGridView1.DataSource = bll.ShowAll();
 7             }
 8             catch {
 9                 MessageBox.Show("链接数据库出错");
10             }
11         }

帮助类写完之后就开始写数据库操做业务了,在这里说一下,帮助类微软专门有自己封装的类,可以直接下载使用。数据访问代码如下:这里有简易的增删查方法

现在就是考虑实现的时候了。首先写注册,

 

图片 26图片 27

图片 28图片 29

View Code

 

今天我们来说说三层,首先我们来看一下百度百科对于三层架构的解释:三层架构(3-tier
architecture) 通常意义上的三层架构就是将整个业务应用划分为:界面层(User
Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data
access
layer)。区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或称为领域层)、表示层。

View Code

修改实体代码如下

图片 30

1 CREATE TABLE [dbo].[Users]
2 (
3     [Id] INT NOT NULL PRIMARY KEY IDENTITY(1,1), 
4     [Name] NVARCHAR(50) NOT NULL, 
5     [Pass] NVARCHAR(50) NOT NULL
6 )

首先先解释第一个问题,我们的Name显示的确实ID编号,这个就是我们的实体类缺失Id这个属性,但是在查询的时候查询的缺失所有的属性,这样子就出现了这个显示没有对齐的现象,怎么解决呢,两个方法,第一修改查询条件,只查询Name和Pass,第二我们添加实体ID,我们就用第二种方法吧。

 1      private void button2_Click(object sender, EventArgs e)
 2         {
 3             try
 4             {
 5                 //新建一个类,这里使用无参的构造函数,方便以后反射
 6                 People p = new People();
 7 
 8                 //为它的属性赋值
 9                 p.Name = textBox1.Text.ToString();
10                 p.Password = textBox2.Text.ToString();
11 
12                 //调用bll的添加业务
13                 string message = bll.Add(p) ? "添加成功" : "添加失败";
14 
15                 MessageBox.Show(message);
16             }
17             catch
18             {
19                 throw;
20             }
21         }

第一步我们创建一个解决方案,里面添加三个类库,如下图所示:

现在我们先来开始写数据访问层,在数据访问层里,我们首先建立一个帮助类SQLServerDALHelper,实现数据连接,代码如下:

View Code

现在我们所需要的增删查问题都已经实现了,但是还有问题,什么问题呢,我们在运行程序的时候会发先dataGridView显示数据在执行增删之后都不进行刷新,所以在执行这两个操做的时候业务执行了可是数据却无法刷新到dataGridView控件中,我们应该用什么办法解决呢?我们不是写了一个shows()方法用来显示数据吗,我们只要在需要数据刷新的地方调用这个方法就行了,实现很简单,我就不具体改了,大家下来自己要实现的改一下就好了。今天的内容已经写完了,希望大家支持,文中有错误希望大家能够指出来,让我学习改正。

接下来就是业务逻辑层了,这个层就需要引用DAL层和Entityc层了,

View Code

图片 31图片 32

 1   public static List<People> ConvertReaderToTicketList(SqlDataReader dr)
 2          {
 3              List<People> ts = new List<People>();
 4 
 5              if (dr.HasRows)
 6              {
 7                  while (dr.Read())
 8                  {
 9                      ts.Add(new People(dr[0].ToString(), dr[1].ToString(),dr[2].ToString()));
10                  }
11              }
12 
13              return ts;
14          }

这三个类库分别代表的是业务逻辑层BLL,数据访问层DAL,还有实体Entity,下一步就是添加你需要的表现层,我为了表示清楚直接使用了UI命名。图片 33

我们使用三层架构就是为了让整个程序能够更加易于维护,业务逻辑和表现方式还有数据库操做都能够分开来写,这样开发人员也能够更好的分工。而且易于扩展,如果要是业务需求增加活着要删除某个需求,也容易修改。

我们的数据访问层这就已经写完了,这里说到底也都只是套路而已,掌握了套路,所有的东西等于都掌握了。

现在插入数据格式问题也解决了。图片 34

接下来我们先写实体类,实体类映射的是数据库表,所以实体类里面的属性一定要对应数据库中的表。

View Code

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using DAL;
 6 using Entery;
 7 
 8 namespace BLL
 9 {
10     /// <summary>
11     /// 这是BLL 业务逻辑层,此层被表现层(UI)调用,同时它自己调用DAL
12     /// </summary>
13     public class PeopleBLL
14     {
15         PeopleDAL dal = new PeopleDAL();
16 
17         public bool Add(People p){
18             //添加一个用户
19             return dal.Insert(p);
20         }
21 
22         public bool Del(People p) {
23             //删除一个用户
24             return dal.Delete(p);
25         }
26 
27         public bool Sel(People p) {
28             //查询用户
29             return dal.Select(p);
30         }
31 
32         public List<People> ShowAll()
33         {
34             return dal.SelectAll();
35         }
36     }
37 }

这样第一个出现的问题就解决了,下来我们来说第二个问题,这个问题是因为数据格式问题,我们string格式对应的是Varchar()但是我们用的是Nvarchar(),所以我们应该在插入数据这块添加一个N,修改代码如下:

相关文章