您的位置:首页 > 其它

工厂模式简单介绍及应用(以数据导入功能实现为例)

2011-03-11 12:06 405 查看
工厂模式:3W

1W:What?

--提供创建对象的接口

 

2W:Why?  

--相当于new创建实例对象,使用该模式,可以让系统具有更好的扩展性/易维护性和复用性,充分展示了面向对象的特点

      活字印刷技术就是一个面向对象的应用。 (以下内容属于摘抄)

      引:“活字印刷的特点是:第一,要改,只需要更改要改之字,此为可维护;第二,这些字并非用完这次就无用,完全可 以在后来的印刷中重复使用,此乃可复用;第三,若要加字,只需另刻字加入即可,这是可扩展;第四,字的排列可能是竖排可能是横排,此时只需将活字移动就可满足排列需求,此是灵活性好。而在活字印刷术出现之前,上面的四种特性都无法满足。”

 

3W:How?

--以下介绍一个通过Excel表格向数据库导入数据的功能实现,在下面代码的实现过程就是工厂模式的应用。

 

-------------------------介绍完毕,进入代码世界-------------------------

 

第一步:创建前台/后台页面

 

using System;using System.Data;using System.Configuration;using System.Collections;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;using System.IO;using SXInnerWebPersistent.Model;public partial class 导入数据_导入 : BasePage{    #region 属性设置    private string TempUrl = "../Template/StudentInput.xls";  //模板路径    private string errorMsg = string.Empty;  //上传保存时的错误消息    private string FileName = string.Empty;  //上传文件名称    #endregion    protected void Page_Load(object sender, EventArgs e)    {        if (!IsPostBack)        {            isExt(TempUrl);   //判断模板是否存在        }        btnOk.ImageUrl = "../Images/qd5.jpg";    }    /// <summary>    /// 判断模板是否存在:1存在 0不存在    /// </summary>    /// <param name="url">模板路径</param>    private void isExt(string url)    {        try        {            if (File.Exists(Server.MapPath(url)))            {                txtIsExist.Value = "1";                txtTempUrl.Value = url;            }            else            {                txtIsExist.Value = "0";            }        }        catch (Exception ex)        {            Console.Write(ex.Message);            txtIsExist.Value = "0";        }    }    protected void btnOk_Click(object sender, ImageClickEventArgs e)    {        try        {            VolidateFile(ref errorMsg);  //调用一            if (!string.IsNullOrEmpty(errorMsg))            {                tblInfo.Rows[0].Cells[0].InnerHtml = errorMsg;                return;            }            UpLoadFile(ref FileName);  //调用二            AbstractOledbCommon AOC = new ExcelCommon();            AOC.ProConn = string.Format(AOC.ProConnTemp, FileName);                        InputEnty enty = new InputEnty();             enty.IsJump = rbJump.Checked;            enty.InputConn = AOC;            InputClass myInput = InputFactory.CreateObject("StudentInput");            myInput.InputCondition = enty;            myInput.ExecuteInput(this.connStr);            tblInfo.Rows[0].Cells[0].InnerHtml = myInput.InputCondition.SussMsg + myInput.InputCondition.ErrorMsg;            string tmp = "<mce:script language=/"javascript/"><!--proBar.runtimeStyle.visibility=/"hidden/";// --></mce:script>";            if (!IsStartupScriptRegistered("re"))                RegisterStartupScript("re", tmp);        }        catch         {            tblInfo.Rows[0].Cells[0].InnerHtml = "导入失败!请检查导入文件";        }    }    /// <summary>    /// 验证文件    /// </summary>    /// <param name="errorMsg">错误消息</param>    private void VolidateFile(ref string errorMsg)    {        if (!string.IsNullOrEmpty(this.File1.PostedFile.FileName.Trim()))  //判断上传文件是否存在        {            if (this.File1.PostedFile.FileName.Substring(this.File1.PostedFile.FileName.LastIndexOf('.') + 1).Equals("xls"))  //判断上传文件格式            {                if (this.File1.PostedFile.ContentLength > 10485670)  //判断上传文件是否容量过大                {                    errorMsg = "文件过大!请分几次导入!";                }            }            else            {                errorMsg = "导入的文件格式不对,请选择excel文件!";            }        }        else        {            errorMsg = "不能上传空文件";        }    }    /// <summary>    /// 上传文件    /// </summary>    private void UpLoadFile(ref string fileName)    {        fileName = Request.PhysicalApplicationPath + @"TempFile/";  //路径        fileName = fileName + DateTime.Now.ToString("yyyyMMddhhmmss") + ".xls";  //保存名称        File1.PostedFile.SaveAs(fileName);        /*** 这是我注意不到的地方 ***/        File1.Dispose();  //释放资源        GC.Collect();  //垃圾回收    }}


 

第二步:创建一个程序集,命名为SXInnerWebPersistent。在该程序集下建立文件夹Model,在该文件夹下创建类文件InputClass.cs

using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;using System.Collections;using System.Reflection;using System.Data.OleDb;using System.Data.SqlClient;using System.Collections.Generic;using MicrosoftHelper;namespace SXInnerWebPersistent.Model{ /// <summary> /// InputClass 的摘要说明:导入类 /// </summary> public abstract class InputClass { #region 属性 public InputEnty InputCondition = new InputEnty(); private OleDbConnection myConn = null; private DataSet InputDataSet = null; private string[] strSql = null; private string errors = string.Empty; private int ItemCount = 0; //导入项数 protected SqlEnty SqlEnty = new SqlEnty(); protected DataTable FormatTable = null; protected string strTest = string.Empty; protected int successCount = 0; //成功导入个数 protected int fugaiCount = 0; //覆盖导入个数 protected List<StudentEnty> StudentList = new List<StudentEnty>(); #endregion #region 抽象方法 protected abstract void ValidateExcelData(); protected abstract void Insert(); #endregion public InputClass() { // // TODO: 在此处添加构造函数逻辑 // } /// <summary> /// 执行导入功能 /// </summary> /// <param name="con"></param> public void ExecuteInput(string con) { try { SqlEnty.ConnStr = con; //数据库连接 myConn = new OleDbConnection(InputCondition.InputConn.ProConn); //Excel数据连接 myConn.Open(); //打开连接 GetDataSource(); if (!string.IsNullOrEmpty(InputCondition.ErrorMsg)) { return; } ValidateData(); if (!string.IsNullOrEmpty(InputCondition.ErrorMsg)) { return; } InitObject(); Insert(); } catch { InputCondition.ErrorMsg = "请检查导入模版是否正确"; if (SqlEnty.MyTrans != null && SqlEnty != null) { SqlEnty.MyTrans.Rollback(); } } finally { if (SqlEnty != null && SqlEnty.MyConn != null) { SqlEnty.MyConn.Close(); SqlEnty.MyConn.Dispose(); } } } /// <summary> /// 得到数据源 /// </summary> public void GetDataSource() { if (InputCondition.InputConn.ProType.Equals(ProviderType.Excel)) { System.Data.DataTable ExcelTable = myConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); InputCondition.InputTableNmLst.Add(ExcelTable.Rows[0]["TABLE_NAME"].ToString()); } strSql = new string[2] { "select * from [" + InputCondition.InputTableNmLst[0] + "]", "select {0}, count({0}) as num from [" + InputCondition.InputTableNmLst[0] + "] group by {0}" }; InputDataSet = new DataSet(); OleDbDataAdapter ODDA = new OleDbDataAdapter(strSql[0], myConn); ODDA.Fill(InputDataSet, "table1"); FormatTable = InputDataSet.Tables[0]; //查询Sheet1中的所有数据 ItemCount = FormatTable.Rows.Count; ODDA = new OleDbDataAdapter(string.Format(strSql[1], FormatTable.Columns[0].ColumnName),myConn); ODDA.Fill(InputDataSet, "table2"); myConn.Close(); if (InputDataSet.Tables[0] == null || InputDataSet.Tables[0].Rows.Count.Equals(0)) { InputCondition.ErrorMsg += "所选数据源内没有可导入的数据。<br>"; } } /// <summary> /// 验证数据 /// </summary> public void ValidateData() { #region 判断重复 DataRow[] drs = InputDataSet.Tables[1].Select("num>1"); //以入学编号为主键,查询是否有多个相同入学编号的信息 if (drs != null && !drs.Length.Equals(0)) { errors = "监测站编码为{0}的监测站数据有重复,请检查!<br>" + Environment.NewLine; foreach (DataRow dr in drs) { if (dr[0] != System.DBNull.Value && !String.IsNullOrEmpty(dr[0].ToString())) { InputCondition.ErrorMsg += string.Format(errors, dr[0].ToString()); } } return; } #endregion #region 判断主键是否为空,如果主键为空,则判断主键为空的是否存在记录 for (int i = 0; i < InputDataSet.Tables[1].Rows.Count; i++) { if (string.IsNullOrEmpty(InputDataSet.Tables[1].Rows[i][0].ToString())) { if (InputDataSet.Tables[1].Rows[i]["num"].ToString().Equals("0")) { continue; } InputCondition.ErrorMsg += "文件中存在为空的监测站编码<br>" + Environment.NewLine; break; } } #endregion if (!string.IsNullOrEmpty(InputCondition.ErrorMsg)) { return; } if (InputCondition.InputConn.ProType.Equals(ProviderType.Excel)) { ValidateExcelData(); } } /// <summary> /// 初始化 /// </summary> private void InitObject() { SqlEnty.MyConn = new SqlConnection(SqlEnty.ConnStr); SqlEnty.MyConn.Open(); SqlEnty.MyTrans = SqlEnty.MyConn.BeginTransaction(); } protected bool isDate(string times) { try { DateTime tm = Convert.ToDateTime(times); return true; } catch { return false; } } } #region 导入实体类 public class InputEnty { private AbstractOledbCommon _InputConn; /// <summary> /// 导入连接 /// </summary> public AbstractOledbCommon InputConn { get { return _InputConn; } set { _InputConn = value; } } private string _SussMsg; /// <summary> /// 导入成功的信息提示 /// </summary> public string SussMsg { get { return _SussMsg; } set { _SussMsg = value; } } private string _ErrorMsg; /// <summary> /// 导入失败的信息提示 /// </summary> public string ErrorMsg { get { return _ErrorMsg; } set { _ErrorMsg = value; } } private bool _isJump = false; /// <summary> /// 是否覆盖存在数据 默认:跳过 /// </summary> public bool IsJump { get { return _isJump; } set { _isJump = value; } } private List<string> _InputTableNmLst = null; public List<string> InputTableNmLst { get { if (_InputTableNmLst == null) { _InputTableNmLst = new List<string>(); } return _InputTableNmLst; } set { _InputTableNmLst = value; } } } #endregion #region Oledb类 public class AbstractOledbCommon { private ProviderType _ProType; /// <summary> /// 类型 /// </summary> public ProviderType ProType { get { return _ProType; } set { _ProType = value; } } private string _ProConn; /// <summary> /// 连接 /// </summary> public string ProConn { get { return _ProConn; } set { _ProConn = value; } } /// <summary> /// 连接模板 /// </summary> public virtual string ProConnTemp { get { return ProConnTemp; } } } #endregion #region 体现继承性 public class ExcelCommon : AbstractOledbCommon { public ExcelCommon() { ProType = ProviderType.Excel; } public override string ProConnTemp { get { return " Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source ={0};Extended Properties='Excel 8.0;HDR=Yes;IMEX=1';"; } } } public class AccessOledb : AbstractOledbCommon { public AccessOledb() { ProType = ProviderType.Access; } public override string ProConnTemp { get { return " Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}"; } } } public class SqlSvrOledb : AbstractOledbCommon { public SqlSvrOledb() { ProType = ProviderType.SqlSvr; } public override string ProConnTemp { get { return "Provider=SQLOLEDB;Data Source={0};Password={2};User ID={1};Initial Catalog={3}"; } } } #endregion #region 导入类型 public enum ProviderType { Excel = 0, Access = 1, SqlSvr = 2, } #endregion #region 导入工厂 public class InputFactory { public static InputClass CreateObject(string strType) { InputClass IC = null; try { IC = (InputClass)Assembly.Load("SXInnerWebPersistent").CreateInstance("SXInnerWebPersistent.Model." + strType); } catch { } return IC; } } #endregion #region SQL类 public class SqlEnty { private string _ConnStr; /// <summary> /// 数据库连接字符串参数 /// </summary> public string ConnStr { get { return _ConnStr; } set { _ConnStr = value; } } private SqlConnection _MyConn; /// <summary> /// 数据库连接字符串 /// </summary> public SqlConnection MyConn { get { return _MyConn; } set { _MyConn = value; } } private SqlTransaction _MyTrans; /// <summary> /// 数据库事务 /// </summary> public SqlTransaction MyTrans { get { return _MyTrans; } set { _MyTrans = value; } } } #endregion #region 学生访问类 public class StudentInput : InputClass { protected override void ValidateExcelData() { string verror = string.Empty; strTest = "限制长度|SID<5>(学生编码),SNM<8>(学生姓名)//小数带参数|Grade<2-2>(入学成绩)"; MicA.Web.Validate.WebFormValidate wv = new MicA.Web.Validate.WebFormValidate(); IList VErrors = null; // 用来返回检证EXCEL数据的不正确的具体错误  Hashtable t = new Hashtable(); SqlParameter[] pr = new SqlParameter[5]; string[] ItemName = new string[] { "SID", "SNM", "Tm", "Grade", "NT" }; for (int i = 0; i < FormatTable.Rows.Count-1; i++) { for (int j = 0; j < ItemName.Length; j++) { t.Add(ItemName[j].ToString(), FormatTable.Rows[i][j].ToString()); } VErrors = wv.addValidateOnServer(t, strTest); foreach (string ver in VErrors) { verror += ver + " "; } if (!isDate(FormatTable.Rows[i][2].ToString().Trim())) { verror += "入学日期|日期格式不正确,正确的格式信息如 1999-1-1不为空"; } if (string.IsNullOrEmpty(FormatTable.Rows[i][1].ToString())) { InputCondition.ErrorMsg += String.Format("导入第{0}行的姓名必须不为空<br>" + System.Environment.NewLine, (i + 1).ToString()); } if (!string.IsNullOrEmpty(verror)) { InputCondition.ErrorMsg += String.Format("导入第{0}行的数据错误是:{1}<br>" + System.Environment.NewLine, (i + 1).ToString(), verror); } t.Clear(); //移出元素 verror = string.Empty; } } private List<StudentEnty> GetDataList() { List<StudentEnty> objList = new List<StudentEnty>(); string sSql = "SELECT SID,SNM,Tm,Grade,NT from tb_b_StudentInput"; using (SqlDataReader reader = SqlHelper.ExecuteReader(SqlEnty.ConnStr, System.Data.CommandType.Text, sSql)) { while (reader.Read()) { StudentEnty se = new StudentEnty(); _bindInstance(se, reader); objList.Add(se); } } return objList; } /// <summary> /// 实体绑定 /// </summary> /// <param name="obj"></param> /// <param name="data"></param> private static void _bindInstance(StudentEnty obj, IDataReader data) { if (data.IsDBNull(0) == false) { obj.SID = data.GetString(0); } if (data.IsDBNull(1) == false) { obj.SNM = data.GetString(1); } if (data.IsDBNull(2) == false) { obj.Tm = data.GetDateTime(2); } if (data.IsDBNull(3) == false) { obj.Grade = data.GetDecimal(3); } if (data.IsDBNull(4) == false) { obj.NT = data.GetString(4); } } /// <summary> /// 插入数据 /// </summary> protected override void Insert() { if (InputCondition.InputConn.ProType.Equals(ProviderType.Excel)) { ExcelInsert(); } if (fugaiCount != 0) { InputCondition.SussMsg += String.Format("共导入了{0}条数据!覆盖了{1}条数据!", successCount.ToString(), fugaiCount.ToString()); } else { InputCondition.SussMsg += String.Format("共导入了{0}条数据!", successCount.ToString()); } SqlEnty.MyTrans.Commit(); } protected void ExcelInsert() { StudentEnty se = null; for (int i = 0; i < FormatTable.Rows.Count; i++) { if (string.IsNullOrEmpty(FormatTable.Rows[i][0].ToString().Trim())) { continue; } se = new StudentEnty(); _bindInstance2(se, FormatTable.Rows[i]); if (InputCondition.IsJump) { InputCondition.SussMsg += string.Format("导入学生编号为{0}的学生记录时跳过了入学时间为{1}的数据。<br>" + Environment.NewLine, se.SID, se.Tm); continue; } else { try { Delete(se, SqlEnty.MyTrans); } catch { InputCondition.ErrorMsg = "覆盖数据时出现异常"; return; } fugaiCount += 1; } se.SID = FormatTable.Rows[i][0].ToString(); se.SNM = FormatTable.Rows[i][1].ToString(); se.Tm = Convert.ToDateTime(FormatTable.Rows[i][2].ToString()); se.Grade = Convert.ToDecimal(FormatTable.Rows[i][3].ToString()); se.NT = FormatTable.Rows[i][4].ToString(); Insert(se, SqlEnty.MyTrans); successCount += 1; StudentList.Add(se); } } public static void _bindInstance2(StudentEnty obj, DataRow data) { if (data.IsNull(0) == false) { obj.SID = data[0].ToString(); } if (data.IsNull(1) == false) { obj.SNM = data[1].ToString(); } if (data.IsNull(2) == false) { obj.Tm = Convert.ToDateTime(data[2].ToString()); } if (data.IsNull(3) == false) { obj.Grade = Convert.ToDecimal(data[3].ToString()); } if (data.IsNull(4) == false) { obj.NT = data[4].ToString(); } } public void Insert(StudentEnty entity, SqlTransaction sqlst) { string SQL_INSERT = "INSERT INTO tb_b_StudentInput(SID,SNM,Tm,Grade,NT) VALUES(@SID,@SNM,@Tm,@Grade,@NT)"; try { SqlParameter[] paras = getInsertParameters(entity); SqlHelper.ExecuteNonQuery(sqlst, CommandType.Text, SQL_INSERT, paras); } catch (Exception ex) { throw new Exception(ex.Message); } } public void Delete(StudentEnty entity, SqlTransaction sqlst) { string SQL_DELETE = "delete from tb_b_StudentInput where SID in ('" + entity.SID + "') and Tm='" + entity.Tm + "'"; try { SqlHelper.ExecuteNonQuery(sqlst, CommandType.Text, SQL_DELETE); } catch (Exception exx) { throw new Exception(exx.Message); } } public static SqlParameter[] getInsertParameters(StudentEnty obj) { SqlParameter op1 = new SqlParameter("@SID", SqlDbType.Char); op1.Value = obj.SID; SqlParameter op2 = new SqlParameter("@SNM", SqlDbType.Char); op2.Value = obj.SNM; SqlParameter op3 = new SqlParameter("@Tm", SqlDbType.DateTime); op3.Value = obj.Tm; SqlParameter op4 = new SqlParameter("@Grade", SqlDbType.Decimal); op4.Value = obj.Grade; SqlParameter op5 = new SqlParameter("@NT", SqlDbType.Char); op5.Value = obj.NT; return new SqlParameter[] { op1, op2, op3, op4, op5 }; } } #endregion #region 学生实体类 public class StudentEnty { private string _SID; /// <summary> /// 学生编号 /// </summary> public string SID { get { return _SID; } set { _SID = value; } } private string _SNM; /// <summary> /// 学生姓名 /// </summary> public string SNM { get { return _SNM; } set { _SNM = value; } } private DateTime _Tm; /// <summary> /// 入学日期 /// </summary> public DateTime Tm { get { return _Tm; } set { _Tm = value; } } private decimal _Grade; /// <summary> /// 入学成绩 /// </summary> public decimal Grade { get { return _Grade; } set { _Grade = value; } } private string _NT; /// <summary> /// 备注 /// </summary> public string NT { get { return _NT; } set { _NT = value; } } } #endregion}

 

注意:在使用Assembly.Load(程序集名称).CreateInstance(命名空间+类名)有可能会出现错误或是null值

         出现这类问题的原因与解决方法是:

            1.请检查数据层是否实现了接口

               dll下面的具体类是否实现了接口的定义

 

            2.请检查程序集名称和命名空间不一致

               Assembly.Load(path)这里的path必须是一个程序集的名称,而不是类命名空间的名称。

               CreateInstance(CacheKey)这里的CacheKey其实是需要反射的类型全名(程序集名称+类名)

            3.请检查BLL层是否添加了该项目引用

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息