码迷,mamicode.com
首页 > Windows程序 > 详细

C#基础--抽象工厂

时间:2017-12-26 11:57:41      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:interface   server   设计模式   筛选   reader   form   不一致   sel   query   

开发需求:

同一套系统,需要根据客户需求采用不同的数据库。

一般实现:

开发多套系统,每套系统对应一个数据库。

缺点:

需要同时维护多套系统,难度大。

解决:

使用抽象工厂模式,同一套系统里面开发多个数据库的DAL,根据客户需求来确定使用哪个数据库。

抽象工厂设计模式

基于抽象工厂模式设计DAL方案

技术分享图片

项目各层之间的引用

技术分享图片

代码示例

根据以上,建立各层,各层引用参考上面:

技术分享图片

从底层开始构建代码:

编写不同数据库的DAL,我这里仅仅是文件夹形式将Access、SQLServer数据DAL模块分类,实际开发可以使用dll等分层。

技术分享图片仅做了查询Service

IDAL接口定义

DAL需要基于接口开发,所以先定义接口,我们这里仅使用到了两个接口:

using Models;

namespace IDAL
{
    public interface IClassService
    {
        List<StudentClass> GetAllClasses();
    }
}


namespace IDAL
{
    public interface IStudentService
    {
        List<Student> GetStudentsByClassId(int classId);
    }
}

基于接口开发DAL:

Access数据库

AccessHelper:

技术分享图片
 1 using System.Data;
 2 using System.Data.OleDb;
 3 using System.Configuration;
 4 
 5 namespace DAL.Access
 6 {
 7     class AccessHelper
 8     {
 9         private static readonly string connString = ConfigurationManager.ConnectionStrings["AccessConnString"].ToString();
10         public static OleDbDataReader GetReader(string sql)
11         {
12             OleDbConnection conn = new OleDbConnection(connString);
13             OleDbCommand cmd = new OleDbCommand(sql, conn);
14             try
15             {
16                 conn.Open();
17                 return cmd.ExecuteReader(CommandBehavior.CloseConnection);
18             }
19             catch (OleDbException ex)
20             {
21                 if (conn.State == ConnectionState.Open)
22                     conn.Close();
23                 throw new Exception("应用程序与数据库连接异常:" + ex.Message);
24             }
25             catch (Exception ex)
26             {
27                 if (conn.State == ConnectionState.Open)
28                     conn.Close();
29                 throw ex;
30             }
31         }
32     }
33 }
View Code

ClassService:

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using IDAL;
 7 using Models;
 8 using System.Data;
 9 using System.Data.OleDb;
10 
11 namespace DAL.Access
12 {
13     class ClassService : IClassService
14     {
15         public List<StudentClass> GetAllClasses()
16         {
17             string sql = "select * from StudentClass";
18             OleDbDataReader objReader = AccessHelper.GetReader(sql);
19             List<StudentClass> objStuClass = new List<StudentClass>();
20             while (objReader.Read())
21             {
22                 objStuClass.Add(new StudentClass
23                 {
24                     ClassId = Convert.ToInt32(objReader["ClassId"]),
25                     ClassName = objReader["ClassName"].ToString()
26                 });
27             }
28             objReader.Close();
29             return objStuClass;
30         }
31     }
32 }
View Code

StudentService:

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using IDAL;
 7 using System.Data;
 8 using System.Data.OleDb;
 9 using Models;
10 
11 namespace DAL.Access
12 {
13     public class StudentService : IStudentService
14     {
15         public List<Student> GetStudentsByClassId(int classId)
16         {
17             StringBuilder sqlBuilder = new StringBuilder("select StudentId,StudentName,Gender,StudentIdNo,Birthday,PhoneNumber,ClassName,Students.ClassId from Students ");
18             sqlBuilder.Append("inner join StudentClass on StudentClass.ClassId=Students.ClassId ");
19             if (classId > 0)
20                 sqlBuilder.Append($"where Students.ClassId={classId} ");
21             List<Student> stuList = new List<Student>();
22             OleDbDataReader objReader = null;
23             try
24             {
25                 objReader = AccessHelper.GetReader(sqlBuilder.ToString());
26                 while (objReader.Read())
27                 {
28                     stuList.Add(new Student
29                     {
30                         StudentId = Convert.ToInt32(objReader["StudentId"]),
31                         StudentName = objReader["StudentName"].ToString(),
32                         Gender = objReader["Gender"].ToString(),
33                         StudentIdNo = objReader["StudentIdNo"].ToString(),
34                         Birthday = Convert.ToDateTime(objReader["Birthday"]),
35                         PhoneNumber = objReader["PhoneNumber"].ToString(),
36                         ClassName = objReader["ClassName"].ToString(),
37                         ClassId = Convert.ToInt32(objReader["ClassId"])
38                     });
39                 }
40                 return stuList;
41             }
42             catch (Exception ex)
43             {
44                 throw ex;
45             }
46             finally
47             {
48                 objReader.Close();
49             }
50         }
51     }
52 }
View Code

SQLServer数据库

SQLHelper:

技术分享图片
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 using System.Configuration;
  7 using System.Data;
  8 using System.Data.SqlClient;
  9 
 10 namespace DAL.SQLServer
 11 {
 12     class SQLHelper
 13     {
 14         private static readonly string connString=ConfigurationManager.ConnectionStrings["SqlConnString"].ToString();
 15 
 16         /// <summary>
 17         /// 增、删、改,返回受影响行数
 18         /// </summary>
 19         /// <param name="sql"></param>
 20         /// <returns></returns>
 21         public static int Update(string sql)
 22         {
 23             SqlConnection conn = new SqlConnection(connString);
 24             SqlCommand cmd = new SqlCommand(sql, conn);
 25             try
 26             {
 27                 conn.Open();
 28                 return cmd.ExecuteNonQuery();
 29             }
 30             catch (SqlException ex)
 31             {
 32                 if (ex.Number == 547)
 33                     throw new Exception("该数据已被其它表引用,不能直接删除!");
 34                 else
 35                     throw new Exception("数据库操作异常:" + ex.Message);
 36             }
 37             catch (Exception ex)
 38             {
 39                 throw ex;
 40             }
 41             finally
 42             {
 43                 conn.Close();
 44             }
 45         }
 46         
 47 
 48         /// <summary>
 49         /// 仅得到一条数据的查询
 50         /// </summary>
 51         /// <param name="sql"></param>
 52         /// <returns></returns>
 53         public static object GetSingleResult(string sql)
 54         {
 55             SqlConnection conn = new SqlConnection(connString);
 56             SqlCommand cmd = new SqlCommand(sql, conn);
 57             try
 58             {
 59                 conn.Open();
 60                 return cmd.ExecuteScalar();
 61             }
 62             catch (SqlException ex)
 63             {
 64                 throw new Exception("数据库操作异常:" + ex.Message);
 65             }
 66             catch (Exception ex)
 67             {
 68                 throw ex;
 69             }
 70             finally
 71             {
 72                 conn.Close();
 73             }
 74         }
 75 
 76         /// <summary>
 77         /// 查询得到结果集
 78         /// </summary>
 79         /// <param name="sql"></param>
 80         /// <returns></returns>
 81         public static SqlDataReader GetReader(string sql)
 82         {
 83             SqlConnection conn = new SqlConnection(connString);
 84             SqlCommand cmd = new SqlCommand(sql, conn);
 85             try
 86             {
 87                 conn.Open();
 88                 return cmd.ExecuteReader(CommandBehavior.CloseConnection);
 89             }
 90             catch (SqlException ex)
 91             {
 92                 if (conn.State == ConnectionState.Open)
 93                     conn.Close();
 94                 throw new Exception("应用程序与数据库连接异常:" + ex.Message);
 95             }
 96             catch (Exception ex)
 97             {
 98                 if (conn.State == ConnectionState.Open)
 99                     conn.Close();
100                 throw ex;
101             }
102         }
103 
104         /// <summary>
105         /// 查询得到数据集,前台需要多次筛选数据时使用
106         /// </summary>
107         /// <param name="sql"></param>
108         /// <returns></returns>
109         public static DataSet GetDataSet(string sql)
110         {
111             SqlConnection conn = new SqlConnection(connString);
112             SqlCommand cmd = new SqlCommand(sql, conn);
113             SqlDataAdapter da = new SqlDataAdapter(cmd);
114             DataSet ds = new DataSet();
115             try
116             {
117                 conn.Open();
118                 da.Fill(ds);
119                 return ds;
120             }
121             catch (SqlException ex)
122             {
123                 throw new Exception("数据库操作异常:" + ex.Message);
124             }
125             catch (Exception ex)
126             {
127                 throw ex;
128             }
129             finally
130             {
131                 conn.Close();
132             }
133         }
134     }
135 }
View Code

ClassService:

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using IDAL;
 7 using Models;
 8 using System.Data;
 9 using System.Data.SqlClient;
10 
11 namespace DAL.SQLServer
12 {
13     public class ClassService : IClassService
14     {
15         public List<StudentClass> GetAllClasses()
16         {
17             string sql = "select * from StudentClass";
18             SqlDataReader objReader = SQLHelper.GetReader(sql);
19             List<StudentClass> objStuClass = new List<StudentClass>();
20             while (objReader.Read())
21             {
22                 objStuClass.Add(new StudentClass
23                 {
24                     ClassId = Convert.ToInt32(objReader["ClassId"]),
25                     ClassName = objReader["ClassName"].ToString()
26                 });
27             }
28             objReader.Close();
29             return objStuClass;
30         }
31     }
32 }
View Code

StudentService:

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using IDAL;
 7 using Models;
 8 using System.Data;
 9 using System.Data.SqlClient;
10 
11 namespace DAL.SQLServer
12 {
13     public class StudentService : IStudentService
14     {
15         public List<Student> GetStudentsByClassId(int classId)
16         {
17             StringBuilder sqlBuilder = new StringBuilder("select StudentId,StudentName,Gender,StudentIdNo,Birthday,PhoneNumber,ClassName,Students.ClassId from Students ");
18             sqlBuilder.Append("inner join StudentClass on StudentClass.ClassId=Students.ClassId ");
19             if (classId >= 0)//当==-1,说明是选的全部班级,则不需要筛选
20                 sqlBuilder.Append($"where Students.ClassId={classId} ");
21             List<Student> stuList = new List<Student>();
22             SqlDataReader objReader = null;
23             try
24             {
25                 objReader = SQLHelper.GetReader(sqlBuilder.ToString());
26                 while (objReader.Read())
27                 {
28                     stuList.Add(new Student
29                     {
30                         StudentId = Convert.ToInt32(objReader["StudentId"]),
31                         StudentName = objReader["StudentName"].ToString(),
32                         Gender = objReader["Gender"].ToString(),
33                         StudentIdNo = objReader["StudentIdNo"].ToString(),
34                         Birthday = Convert.ToDateTime(objReader["Birthday"]),
35                         PhoneNumber = objReader["PhoneNumber"].ToString(),
36                         ClassName = objReader["ClassName"].ToString(),                       
37                         ClassId = Convert.ToInt32(objReader["ClassId"]),                        
38                     });
39                 }
40                 return stuList;
41             }
42             catch (Exception ex)
43             {
44                 throw ex;
45             }
46             finally
47             {
48                 objReader.Close();
49             }
50         }
51     }
52 }
View Code

App.Config配置

数据库用到了App.Config节点:

技术分享图片
 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3     <startup> 
 4         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
 5     </startup>
 6   <connectionStrings>
 7     <add name="SqlConnString" connectionString="server=.;DataBase=StudentManageDB;Uid=sa;Pwd=warrenwell"/>
 8     <add name="AccessConnString" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=StudentManageDB.mdb"/>
 9   <!--Office版本2007以上使用以上Provider;以下:Microsoft.JET.OLEDB.4.0-->
10   </connectionStrings>
11   <appSettings>
12     <add key="DBType" value="SQLServer"/>
13     <!--<add key="DBType" value="Access"/>-->
14     </appSettings>
15 </configuration>
View Code

Models实体类

使用到的实体类

StudentClass:

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace Models
 8 {
 9     public class StudentClass
10     {
11         public int ClassId { get; set; }
12         public string ClassName { get; set; }
13     }
14 }
View Code

Students:

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace Models
 8 {
 9     public class Student
10     {
11         public int StudentId { get; set; }
12         public string StudentName { get; set; }
13         public string Gender { get; set; }
14         public DateTime Birthday { get; set; }
15         public string StudentIdNo { get; set; }
16         public int Age { get; set; }
17         public string CardNo { get; set; }
18         public string PhoneNumber { get; set; }        
19         public int ClassId { get; set; }
20 
21         public string ClassName { get; set; }
22     }
23 }
View Code

DALFactory

DALFactory根据以上App.Config里appSettings节点的key<"DBType">来选择数据库

DALAccess数据库数据访问创建类:

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Configuration;
 7 using IDAL;
 8 using System.Reflection;
 9 
10 namespace DALFactory
11 {
12     public class DataAccess
13     {
14         private static string dbType = "DAL."+ConfigurationManager.AppSettings["DBType"].ToString();
15 
16         public static IDAL.IClassService CreateClassService()
17         {
18             return (IDAL.IClassService)Assembly.Load("DAL").CreateInstance(dbType + ".ClassService");
19         }
20 
21         public static IDAL.IStudentService CreateStudentService()
22         {
23             return (IDAL.IStudentService)Assembly.Load("DAL").CreateInstance(dbType + ".StudentService");
24         }
25     }
26 }
View Code

应用到了反射,里面Load()里面是数据库的命名空间名称,CreateInstance()里面是相应DAL的完全限定名:命名空间名称.相应Serivce名。

BLL

我们把数据访问的内容全部放到BLL里面,从而完全断绝UI与DAL的耦合。

ClassManager:

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using DALFactory;
 7 using Models;
 8 using IDAL;
 9 
10 namespace BLL
11 {
12     public class ClassManager
13     {
14         IDAL.IClassService objService = DALFactory.DataAccess.CreateClassService();
15         public List<StudentClass> GetAllClasses()
16         {
17             return objService.GetAllClasses();
18         }
19     }
20 }
View Code

StudentManager:

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using DALFactory;
 7 using Models;
 8 using IDAL;
 9 
10 namespace BLL
11 {
12     public class StudentManager
13     {
14         IDAL.IStudentService objService = DALFactory.DataAccess.CreateStudentService();
15         public List<Student> GetStudentsByClassId(int classId)
16         {
17             return objService.GetStudentsByClassId(classId);
18         }
19     }
20 }
View Code

UI

仅写了查询班级与学生(UI设计见下面结果展示):

技术分享图片
 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Threading.Tasks;
 9 using System.Windows.Forms;
10 using BLL;
11 using Models;
12 
13 namespace AbstractFactoryDemo
14 {
15     public partial class FrmQuery : Form
16     {
17         public FrmQuery()
18         {
19             InitializeComponent();
20 
21             List<StudentClass> stuClass = new List<StudentClass>()
22             {
23                 new StudentClass {ClassId=-1,ClassName="全部班级" }
24             } ;
25             stuClass.AddRange(new ClassManager().GetAllClasses());
26 
27             this.cboStudentClass.DataSource = stuClass;
28             this.cboStudentClass.DisplayMember = "ClassName";
29             this.cboStudentClass.ValueMember = "ClassId";
30 
31             this.dgvStudentList.AutoGenerateColumns = false;
32         }
33 
34         private void btnQuery_Click(object sender, EventArgs e)
35         {
36             this.dgvStudentList.DataSource = new StudentManager().GetStudentsByClassId(Convert.ToInt32(this.cboStudentClass.SelectedValue));
37         }
38     }
39 }
View Code

结果展示

我们可以通过配置App.Config的相应节点来控制访问哪个数据库。

比如,我们先访问SQLServer,就这样:

技术分享图片

访问结果:

技术分享图片

 再去访问Access:

技术分享图片

访问结果:

技术分享图片

故意将两个数据库的数据格式不一致,比较容易看出来差别。

至此,抽象工厂设计模式完成。

相应源代码+数据库脚本

 https://files.cnblogs.com/files/EasonDongH/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%E6%BA%90%E4%BB%A3%E7%A0%81And%E6%95%B0%E6%8D%AE%E5%BA%93%E8%84%9A%E6%9C%AC.zip

注意点

有个地方需要注意,关于DAL.dll文件,如果提示不存在,则需要手动到DAL程序集下将该DAL.dll复制到项目下;如果提示“源文件与模块不一致”这样的错误,则表示你的DAL有做修改,重新生成一下DAL,再次重新将dll文件复制过去。这是经验之谈,暂未更好的解决方案,等待指教。

 

C#基础--抽象工厂

标签:interface   server   设计模式   筛选   reader   form   不一致   sel   query   

原文地址:https://www.cnblogs.com/EasonDongH/p/8116890.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!