C# 三层架构与N层架构

日之朝矣

三层架构

三层架构由 表示层(UI),业务逻辑层(BLL),数据访问层(DAL)组成

  • 表示层(User Interface,UI):负责与用户的交互,展示数据,并收集用户输入。表示层通常包括用户界面元素,如窗体、按钮、文本框等。
  • 业务逻辑层(Business Logic Layer, BLL):包含应用程序的核心业务逻辑。负责处理应用程序的数据处理规则和业务流程。
  • 数据访问层(Data Access Layer,DAL):负责与数据库或其他数据源的交互。它将业务逻辑层请求的数据存储或从数据源中提取数据并传递回业务逻辑层。

优点:

分离关注点:每一层都有明确的职责,使得各层的代码可以独立开发、测试和维护。

提高可维护性:由于层次之间的依赖关系较弱,修改一层的代码通常不会影响到其他层,从而降低了维护的复杂性。

提高可扩展性:通过增加或替换某一层的实现,可以轻松扩展应用程序的功能。例如,可以更换数据访问层以支持不同的数据库系统。

增强代码重用性:业务逻辑层和数据访问层中的代码可以在不同的应用程序或表示层中重用。

示例

在本例中,在同一个解决方案下创建了四个项目,三个为 类库项目,一个为桌面应用程序项目。

  • UI:桌面应用程序项目
  • BLL:类库项目
  • DAL:类库项目
  • Model: 类库项目

Model:主要存放数据结构

1
2
3
4
5
6
7
8
9
// Student.cs
namespace Model
{
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
}

DAL :负责与数据源交互,这里使用List<T>作为数据源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// StudentDAL.cs
using Model;
using System.Collections.Generic;

namespace DAL
{
public class StudentDAL
{
private List<Student> students = new List<Student>()
{
new Student(){ Id = 1, Name = "张三" },
new Student(){ Id = 2, Name = "李四" },
};
public List<Student> GetAll()
{
return students;
}

public bool Add(Student s)
{
students.Add(s);
return true;
}

public bool Delete(int id)
{
int index = students.FindIndex(stu => stu.Id == id);
if (index == -1) return false;
students.RemoveAt(index);
return true;
}

public bool Update(Student s)
{
int index = students.FindIndex(stu => stu.Id == s.Id);
if (index == -1) return false;
students[index] = new Student()
{
Id = s.Id,
Name = s.Name,
};
return true;
}

public int GetMaxId()
{
if (students.Count == 0) return 0;
return students[students.Count-1].Id;
}
}
}

BLL:处理应用程序的数据处理规则和业务流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// StudentBLL.cs
using DAL;
using Model;
using System.Collections.Generic;

namespace BLL
{
public class StudentBLL
{
private StudentDAL studentDAL = new StudentDAL();

public List<Student> GetAll()
{
return studentDAL.GetAll();
}

public bool Add(Student s)
{
return studentDAL.Add(s);
}

public bool Delete(int id)
{
return studentDAL.Delete(id);
}

public bool Update(Student s)
{
return studentDAL.Update(s);
}

public int GetMaxId()
{
return studentDAL.GetMaxId();
}
}
}

UI:界面就四个按钮,分别负责增删改查,一个DataGridView负责展示数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using BLL;
using Model;
using System;
using System.Windows.Forms;

namespace 三层架构
{
public partial class Form1 : Form
{

private StudentBLL studentBLL = null;
public Form1()
{
studentBLL = new StudentBLL();
InitializeComponent();
}

private void btnGet_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = null;
dataGridView1.DataSource = studentBLL.GetAll();
}

private void btnAdd_Click(object sender, EventArgs e)
{
Student s = new Student()
{
Id = studentBLL.GetMaxId() + 1,
Name = "王五"
};
if (studentBLL.Add(s))
{
btnGet.PerformClick();
}
}

private void btnUpdate_Click(object sender, EventArgs e)
{
Student s = new Student()
{
Id = 1,
Name = "ww"
};
if (studentBLL.Update(s))
{
btnGet.PerformClick();
}
}

private void btnDelete_Click(object sender, EventArgs e)
{
if (studentBLL.Delete(2))
{
btnGet.PerformClick();
}
}
}
}

N层架构

Model 层代表了应用程序中的业务实体或数据结构。它定义了与数据库中的表对应的类,以及这些类的属性。
用于表示应用程序中的数据对象,如用户、订单、产品等。

IDAL 层定义了数据访问层(DAL)所需实现的接口。这些接口定义了对数据库的基本操作方法,如增、删、改、查。
提供一个抽象层,使得数据访问层的具体实现可以与业务逻辑层分离。

DAL 层实现了 IDAL 接口,负责与数据库的直接交互,执行数据库的操作,如查询、插入、更新和删除。
将数据从数据库中提取出来,或将数据存储到数据库中。

DALFactory 层是一个工厂类,负责创建具体的 DAL 实现实例。它根据配置或运行时的需要,动态实例化并返回具体的 DAL 实现。
通过工厂模式来隔离业务逻辑层(BLL)与具体的 DAL 实现,提供一种灵活的方式来选择不同的 DAL 实现。

BLL 层是业务逻辑的核心,负责处理应用程序中的业务规则和流程。它调用 DAL 层来获取或存储数据,并将这些数据处理后传递给 UI 层。
实现具体的业务功能,例如订单处理、用户管理、数据验证等

UI 层是用户界面,负责与用户交互。它显示数据,并将用户的输入传递给 BLL 层进行处理。
处理用户事件、显示数据和反馈操作结果。

DBUtility层(非必要层):工具层,和数据库连接或操作数据库,类型转换工具等等,各种工具。建议:helper结尾,

优点

  1. 松耦合:通过使用接口(IDAL)和工厂模式(DALFactory),各层之间的依赖关系减少,使得各层可以独立变化。
  2. 灵活性:可以在不修改业务逻辑层(BLL)的情况下替换不同的数据库访问实现(DAL)。
  3. 可测试性:由于各层之间的耦合度低,可以更容易地进行单元测试。

示例

在本例中,在同一个解决方案下创建了六个项目,五个为 类库项目,一个为桌面应用程序项目。

  • UI:桌面应用程序项目
  • BLL:类库项目
  • DALFactory:类库项目
  • DAL:类库项目
  • IDAL:类库项目
  • Model: 类库项目

model:

1
2
3
4
5
6
7
8
9
10
// Student.cs
namespace Model
{
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
}

IDAL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// IDALBase.cs
using System.Collections.Generic;

namespace IDAL
{
public interface IDALBase<T>
{
bool Add(T t);
bool Remove(int id);
bool Update(T t);
List<T> GetAll();
T GetModel(int id);

int GetMaxId();
}
}
1
2
3
4
5
6
7
8
9
10
// IStudentDAL.cs
using Model;

namespace IDAL
{
public interface IStudentDAL : IDALBase<Student>
{
Student GetFormIndex(int index);
}
}

DAL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// StudentDAL.cs
using IDAL;
using Model;
using System.Collections.Generic;

namespace DAL
{
public class StudentDAL : IStudentDAL
{
private List<Student> students = new List<Student>()
{
new Student(){ Id=1, Name="张三" },
new Student(){ Id=2, Name="李四" },
};

public bool Add(Student t)
{
Student s = new Student()
{
Id = GetMaxId() + 1,
Name = t.Name,
};
students.Add(t);
return true;
}

public int GetMaxId()
{
if (students.Count == 0) return 0;
return students[students.Count - 1].Id;
}

public List<Student> GetAll()
{
return students;
}

public Student GetFormIndex(int index)
{
return students[index];
}

public Student GetModel(int id)
{
return students.Find(stu => stu.Id == id);
}

public bool Remove(int id)
{
int index = students.FindIndex(stu => stu.Id == id);
if (index == -1) return false;
students.RemoveAt(index);
return true;
}

public bool Update(Student t)
{
int index = students.FindIndex(stu => stu.Id == t.Id);
students[index] = new Student
{
Id = t.Id,
Name = t.Name,
};
return true;
}
}
}

DALFactory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// DataCache.cs
using System.Web;

namespace DALFactory
{
public class DataCache
{
public static object GetCache(string cacheKey)
{
System.Web.Caching.Cache objCache = HttpRuntime.Cache;
return objCache.Get(cacheKey);
}

public static void SetCache(string cacheKey, object value)
{
System.Web.Caching.Cache objCache = HttpRuntime.Cache;
objCache.Insert(cacheKey, value);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// DataAccess.cs
using IDAL;
using System.Reflection;
using System.Web.Configuration;

namespace DALFactory
{
public class DataAccess
{
private static readonly string AssemblyPath = WebConfigurationManager.AppSettings.Get("DAL");

private static object CreateObject(string assemblyPath, string classNameSpace)
{
object objType = DataCache.GetCache(classNameSpace);
if (objType == null)
{
try
{
objType = Assembly.Load(assemblyPath).CreateInstance(classNameSpace);
DataCache.SetCache(classNameSpace, objType);
}
catch
{ }
}
return objType;
}

public static IStudentDAL CreateStudent()
{
string ClassNameSpace = AssemblyPath + ".StudentDAL";
object obj = CreateObject(AssemblyPath, ClassNameSpace);
return (IStudentDAL)obj;
}

}
}

BLL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// StudentBLL.cs
using DALFactory;
using IDAL;
using Model;
using System.Collections.Generic;

namespace BLL
{
public class StudentBLL
{
private readonly IStudentDAL dal = DataAccess.CreateStudent();
public bool Add(Student t) { return dal.Add(t); }

public List<Student> GetAll() { return dal.GetAll(); }

public Student GetFormIndex(int index) { return dal.GetFormIndex(index); }

public Student GetModel(int id) { return dal.GetModel(id); }

public bool Remove(int id) { return dal.Remove(id); }

public bool Update(Student t) { return dal.Update(t); }

public int GetMaxInt() { return dal.GetMaxId(); }
}
}

UI:还是四个按钮与一个DataGridView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using BLL;
using Model;
using System;
using System.Windows.Forms;

namespace N层架构
{
public partial class Form1 : Form
{
private StudentBLL bll = new StudentBLL();
public Form1()
{
InitializeComponent();
}


private void button1_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = null;
dataGridView1.DataSource = bll.GetAll();
}

private void button2_Click(object sender, EventArgs e)
{
Student s = new Student()
{
Id = bll.GetMaxInt() + 1,
Name = "王五"
};
bll.Add(s);
button1.PerformClick();
}

private void button3_Click(object sender, EventArgs e)
{
Student s = new Student()
{
Id = 1,
Name = "ww"
};
if (bll.Update(s))
{
button1.PerformClick();
}
}

private void button4_Click(object sender, EventArgs e)
{
if (bll.Remove(1))
{
button1.PerformClick();
}
}
}
}
  • 标题: C# 三层架构与N层架构
  • 作者: 日之朝矣
  • 创建于 : 2024-08-10 15:03:32
  • 更新于 : 2024-08-18 09:25:27
  • 链接: https://blog.rzzy.fun/2024/08/10/csharp-layered-architecture/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
此页目录
C# 三层架构与N层架构