.Net MVC 三层架构框架

asp.net+ef mvc三层框架搭建过程如下

先创建Model层

创建数据访问接口层IUserInfoDal

在该接口中定义了常见的方法CRUD以及分页方法

1
2
3
4
5
6
7
8
public interface IUserInfoDal
{
IQueryable<UserInfo> LoadEntities(System.Linq.Expressions.Expression<Func<UserInfo, bool>> whereLambda);
IQueryable<UserInfo> LoadPageEntities<s>(int pageIndex, int pageSize, out int totalCount, System.Linq.Expressions.Expression<Func<UserInfo, bool>> whereLambda, System.Linq.Expressions.Expression<Func<UserInfo, s>> orderbyLambda, bool isAsc);
bool DeleteEntity(UserInfo entity);
bool EditEntity(UserInfo entity);
UserInfo AddEntity(UserInfo entity);
}
每个接口中都需要CURD以及分页方法的定义, 而且这些方法的定义基本上是一致的, 所以封装. 封装到IBaseDal
1
2
3
4
5
6
7
8
public interface IBaseDal<T>where T:class,new()//注意该泛型的使用
{
IQueryable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda);
IQueryable<T> LoadPageEntities<s>(int pageIndex, int pageSize, out int totalCount, System.Linq.Expressions.Expression<Func<T, bool>> whereLambda, System.Linq.Expressions.Expression<Func<T, s>> orderbyLambda, bool isAsc);
bool DeleteEntity(T entity);
bool EditEntity(T entity);
T AddEntity(T entity);
}
让IUserInfoDal继承IBaseDal
1
2
3
4
public interface IUserInfoDal:IBaseDal<UserInfo>
{
//定义自己特有的方法。
}
让具体的数据操作类UserInfoDal去实现IUserInfoDal接口中的方法
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
public class UserInfoDal :IUserInfoDal
{
OAEntities Db = new OAEntities();
/// <summary>
/// 查询过滤
/// </summary>
/// <param name="whereLambda"></param>
/// <returns></returns>
public IQueryable<UserInfo> LoadEntities(System.Linq.Expressions.Expression<Func<UserInfo, bool>> whereLambda)
{
return Db.UserInfo.Where<UserInfo>(whereLambda);//
}
/// <summary>
/// 分页
/// </summary>
/// <typeparam name="s"></typeparam>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalCount"></param>
/// <param name="whereLambda"></param>
/// <param name="orderbyLambda"></param>
/// <param name="isAsc"></param>
/// <returns></returns>
public IQueryable<UserInfo> LoadPageEntities<s>(int pageIndex, int pageSize, out int totalCount, System.Linq.Expressions.Expression<Func<UserInfo, bool>> whereLambda, System.Linq.Expressions.Expression<Func<UserInfo, s>> orderbyLambda, bool isAsc)
{
var temp = Db.UserInfo.Where<UserInfo>(whereLambda);
totalCount = temp.Count();
if (isAsc)//升序
{
temp = temp.OrderBy<UserInfo, s>(orderbyLambda).Skip<UserInfo>((pageIndex - 1) * pageSize).Take<UserInfo>(pageSize);
}
else
{
temp = temp.OrderByDescending<UserInfo, s>(orderbyLambda).Skip<UserInfo>((pageIndex - 1) * pageSize).Take<UserInfo>(pageSize);
}
return temp;
}

/// <summary>
/// 删除
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool DeleteEntity(UserInfo entity)
{
Db.Entry<UserInfo>(entity).State = System.Data.EntityState.Deleted;
return Db.SaveChanges() > 0;
}

/// <summary>
/// 更新
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool EditEntity(UserInfo entity)
{
Db.Entry<UserInfo>(entity).State = System.Data.EntityState.Modified;
return Db.SaveChanges() > 0;
}

/// <summary>
/// 添加数据
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public UserInfo AddEntity(UserInfo entity)
{
Db.Set <UserInfo>().Add(entity);
Db.SaveChanges();
return entity;
}
}
```

##### 由于每个数据操作类都要实现自己的接口(每一个接口都继承了IBaseDal),所以每个数据操作类中都要重复实现CURD以及分页的方法,所以把具体的实现封装到了BaseDal中。

```cs
public class BaseDal<T>where T:class,new()
{
OAEntities Db = new OAEntities();
/// <summary>
/// 查询过滤
/// </summary>
/// <param name="whereLambda"></param>
/// <returns></returns>
public IQueryable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda)
{
return Db.Set <T>().Where<T>(whereLambda);//
}

/// <summary>
/// 分页
/// </summary>
/// <typeparam name="s"></typeparam>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalCount"></param>
/// <param name="whereLambda"></param>
/// <param name="orderbyLambda"></param>
/// <param name="isAsc"></param>
/// <returns></returns>
public IQueryable<T> LoadPageEntities<s>(int pageIndex, int pageSize, out int totalCount, System.Linq.Expressions.Expression<Func<T, bool>> whereLambda, System.Linq.Expressions.Expression<Func<T, s>> orderbyLambda, bool isAsc)
{
var temp = Db.Set<T>().Where<T>(whereLambda);
totalCount = temp.Count();
if (isAsc)//升序
{
temp = temp.OrderBy<T, s>(orderbyLambda).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
}
else
{
temp = temp.OrderByDescending<T, s>(orderbyLambda).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
}
return temp;
}

/// <summary>
/// 删除
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool DeleteEntity(T entity)
{
Db.Entry<T>(entity).State = System.Data.EntityState.Deleted;
return Db.SaveChanges() > 0;
}

/// <summary>
/// 更新
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool EditEntity(T entity)
{
Db.Entry<T>(entity).State = System.Data.EntityState.Modified;
return Db.SaveChanges() > 0;
}

/// <summary>
/// 添加数据
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public T AddEntity(T entity)
{
Db.Set <T>().Add(entity);
Db.SaveChanges();
return entity;
}
}
让UserInfoDal继承BaseDal.
1
2
3
4
public class UserInfoDal : BaseDal<UserInfo>,IUserInfoDal
{
//对应的独特方法
}
创建DBSession(数据会话层:就是一个工厂类,负责完成所有数据操作类实例的创建,然后业务层通过数据会话层来获取要操作数据类的实例. 所以数据会话层将业务层与数据层解耦. 在数据会话层中提供一个方法:完成所有数据的保存.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private IUserInfoDal _UserInfoDal;
public IUserInfoDal UserInfoDal
{
get
{
if (_UserInfoDal == null)
{
_UserInfoDal = new UserInfoDal();
}
return _UserInfoDal;
}
set
{
_UserInfoDal = value;
}
}
在数据会话层中提供一个方法:完成所有数据的保存
1
2
3
4
5
6
7
8
/// <summary>
/// 一个业务中经常涉及到对多张操作,我们希望连接一次数据库,完成对张表数据的操作。提高性能。 工作单元模式。
/// </summary>
/// <returns></returns>
public bool SaveChanges()
{
return Db.SaveChanges() > 0;
}
将数据层中的所有的保存数据的SaveChanges注释掉

在数据层中用到了EF的实例,数据会话层中也用到了,所以在一个请求中只能创建一个EF实例(线程内唯一对象)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// <summary>
/// 负责创建EF数据操作上下文实例,必须保证线程内唯一.
/// </summary>
public class DBContextFactory
{
public static DbContext CreateDbContext()
{
DbContext dbContext = (DbContext)CallContext.GetData("dbContext");
if (dbContext == null)
{
dbContext = new OAEntities();
CallContext.SetData("dbContext", dbContext);
}
return dbContext;
}
}
在DBSession和BaseDal中调用上面的方法(CreateDbContext)完成EF实例的创建
1
2
3
4
5
6
7
8
9
10
11
// DBSession获取EF实例
public DbContext Db
{
get
{
return DBContextFactory.CreateDbContext();
}
}

// BaseDal中获取EF的实例
DbContext Db = DAL.DBContextFactory.CreateDbContext();
抽象工厂封装数据操作类实例创建,然后DBSession调用抽象工厂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/// <summary>
/// 通过反射的形式创建类的实例
/// </summary>
public class AbstractFactory
{
private static readonly string AssemblyPath = ConfigurationManager.AppSettings["AssemblyPath"];
private static readonly string NameSpace = ConfigurationManager.AppSettings["NameSpace"];
public static IUserInfoDal CreateUserInfoDal()
{
string fullClassName = NameSpace + ".UserInfoDal";
return CreateInstance(fullClassName) as IUserInfoDal;
}
private static object CreateInstance(string className)
{
var assembly= Assembly.Load(AssemblyPath);
return assembly.CreateInstance(className);
}
}
然后修改DBSession
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private IUserInfoDal _UserInfoDal;
public IUserInfoDal UserInfoDal
{
get
{
if (_UserInfoDal == null)
{
//_UserInfoDal = new UserInfoDal();
_UserInfoDal = AbstractFactory.CreateUserInfoDal();//通过抽象工厂封装了类的实例的创建
}
return _UserInfoDal;
}
set
{
_UserInfoDal = value;
}
}
定义DBSession的接口
1
2
3
4
5
6
7
8
9
/// <summary>
/// 业务层调用的是数据会话层的接口。
/// </summary>
public interface IDBSession
{
DbContext Db { get; }
IUserInfoDal UserInfoDal { get; set; }
bool SaveChanges();
}
然后让DBSession实现该接口

定义具体的业务基类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//在业务基类中完成DBSession的调用,然后将业务层中公共的方法定义在基类中,但是这些方法不知道通过DBSession来获取哪个数据操作类的实例。所以将该业务基类定义成抽象类,加上一个抽象方法,加上一个IBaseDal属性,并且让基类的构造方法调用抽象方法目的是在表现层new具体的业务子类,父类的构造方法被调用,这些执行抽象方法,但是执行的的是子类中具体的实现。业务子类知道通过DBSession获取哪个数据操作类的实例。
public abstract class BaseService<T> where T:class,new()
{
public IDBSession CurrentDBSession
{
get
{
return new DBSession();//暂时
}
}
public IDAL.IBaseDal<T> CurrentDal { get; set; }
public abstract void SetCurrentDal();
public BaseService()
{
SetCurrentDal();//子类一定要实现抽象方法。
}
public IQueryable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T, bool>> whereLambda)
{
return CurrentDal.LoadEntities(whereLambda);
}
}
定义业务层的接口

将数据库链接字符串拷贝到web.config文件中


.Net MVC 三层架构框架
http://blog.chcaty.cn/2018/03/10/net-mvc-san-ceng-jia-gou-kuang-jia/
作者
caty
发布于
2018年3月10日
许可协议