zoukankan      html  css  js  c++  java
  • C#基础--抽象工厂

    开发需求:

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

    一般实现:

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

    缺点:

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

    解决:

    使用抽象工厂模式,同一套系统里面开发多个数据库的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文件复制过去。这是经验之谈,暂未更好的解决方案,等待指教。

  • 相关阅读:
    Java如何编写自动售票机程序
    install windows service
    redis SERVER INSTALL WINDOWS SERVICE
    上传文件
    This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed.
    解决Uploadify上传控件加载导致的GET 404 Not Found问题
    OracleServiceORCL服务不见了怎么办
    Access to the temp directory is denied. Identity 'NT AUTHORITYNETWORK SERVICE' under which XmlSerializer is running does not have sufficient permiss
    MSSQL Server 2008 数据库安装失败
    数据库数据导出成XML文件
  • 原文地址:https://www.cnblogs.com/EasonDongH/p/8116890.html
Copyright © 2011-2022 走看看