转载

MVC实战起步(一):一个简易框架的搭建

三:Infrastructure层建设 一:引言

这仅仅是一个新手写给新手共同入门的博文!这是一个使用MVC,和一些主流框架(Autofac,Log4Net等)来完成的一个简单的项目。和各位学习MVC的朋友们一起学习。

二:项目分层

MVC实战起步(一):一个简易框架的搭建

如左图所示,先建好文件夹,然后再来填充内容。

一:Zero,MVC4.0项目

二:Domain: Abstract仓储类接口,Concrete仓储类实现,Entities实体模型

三:Infrastructure:基础设施

四:IOC:主要用于解耦仓储类接口

三:Infrastructure层建设

首先,从最底层写起:

第一步,写一个操作数据库的类

我这边采用的是底层使用ADO.NET,通过泛型约束和反射来实现一个简单的ORM

1:先在Conntion里面放一个SQLHelper类(找个自己熟悉的),这里就不做工厂了。怎么简单怎么来,先让东西跑起来

2:写个属于自己的ORM类:我们先来想想,如果不考虑存储过程(返回集合,直接LINQ处理数据),我们需要什么东西来拼接SQL语句,首先,要有表名,然后主键,然后各个字段名称,其他的先不考虑,现在写一个IDateBase抽象类来约束实体类,往Infrastructure层的IBase文件夹里新建一个IDateBase抽象类,代码如下:

namespace Zero.Infrastructure.IBase {  public abstract class IDataBase  {   public virtual string TableName { get; set; }   public virtual int ID { get; set; }  } } abstract class IDataBase 

这样就解决了表名和主键名称在用泛型的时候,取不到的问题了,但是字段名称不行啊,每个表的字段都不一样,所以最后还是要用到反射,写一个特性来反射,在Infrastructure层的Attributes文件夹下面建立一个类DataFieldAttribute

代码如下:

namespace Zero.Infrastructure.Attributes {  public class DataFieldAttribute : Attribute  {   private string _FieldName;   public DataFieldAttribute(string fieldname)   {    this._FieldName = fieldname;   }   public string FieldName   {    get { return this._FieldName; }    set { this._FieldName = value; }   }  } } 

完事具备,我们先写一个实体类,然后开始写ORM

实体里建立在Domain的Entities文件夹下面,记得Domain层要引用Infrastructure层

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Zero.Infrastructure.Attributes; using Zero.Infrastructure.IBase; namespace Zero.Domain.Entities {  public class User: IDataBase  {   public User()   {    TableName = "User";   }   private string _TableName;   public override string TableName   {    get    {     if (_TableName == null)     { return "User"; }     else { return _TableName; }    }    set { _TableName = value; }   }   public override int ID { get; set; }   [DataFieldAttribute("UserName")]   public string UserName { get; set; }  } } View Code 

代码如上

现在开始写自己的ORM类

在Infrastructure层的Conntion文件夹下面建立一个ZeroORM类,ORM需要实现的功能有:查询,添加,更改,删除,4个基本功能

public class ZeroORMwhere<T> where T : IBase.IDataBase {      public string SqlConnctionString { get; set; }     public SqlConnection conn { get; set; }     public SqlTransaction tran { get; set; }  }

然后增加查询方法:

/// <summary> /// 获得实体T所有数据 /// </summary> /// <returns></returns> public List<T> Select(T t) {  List<T> list = new List<T>();  string sql = "select * from " + t.TableName + " WITH (NOLOCK) order by id desc";  DataSet ds = SqlHelper.ExecuteDataset(SqlConnctionString, CommandType.Text, sql);  for (int i = 0; i < ds.Tables[0].Rows.Count; i++)  {   list.Add(DataSetToEntity.DsToEntity<T>(ds, i));  }  return list; } 

DataSetToEntity这个类就是网上找的Dataset转实体的方法,大家可以网上找下,最后返回一个List集合

然后是添加方法

/// <summary>     /// 插入新数据     /// </summary>     /// <param name="t">实体类</param>     /// <returns></returns>     public int Insert(T t)     {      try      {       Type mytype = t.GetType();       // 获取类的所有公共属性       System.Reflection.PropertyInfo[] pInfo = mytype.GetProperties();       string FieldName = "";//字段名称       string Values = "";//值       StringBuilder sql = new StringBuilder();       List<SqlParameter> paras = new List<SqlParameter>();//不定参集合,防注入       sql.Append("Insert into ");       sql.Append(mytype.Name);//数据库表名,可以放t.TableName       sql.Append("(");       object[] objDataFieldAttribute = null;       foreach (System.Reflection.PropertyInfo pio in pInfo)       {        objDataFieldAttribute = pio.GetCustomAttributes(typeof(DataFieldAttribute), false);        if (objDataFieldAttribute != null && objDataFieldAttribute.Length > 0)        {         FieldName += ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + ",";//给字段赋值         Values += "@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + ",";//给对应字段的值赋值         paras.Add(new SqlParameter("@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName, pio.GetValue(t, null)));//添加不定参        }       }       FieldName = FieldName.TrimEnd(',');       Values = Values.TrimEnd(',');       sql.Append(FieldName);       sql.Append(") VAlUES (");       sql.Append(Values);       sql.Append(")");       int i = SqlHelper.ExecuteNonQuery(SqlConnctionString, CommandType.Text, sql.ToString(), paras.ToArray());       return i;      }      catch (Exception)      {       return -1;       throw;      }     } View Code 

还有修改和删除方法,以及带事务的方法,一起贴出来。

using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Reflection; using System.Text; using Zero.Infrastructure.Attributes; using Zero.Infrastructure.Utilities; namespace Zero.Infrastructure.Conntion {  public class ZeroORM<T> where T : IBase.IDataBase  {   public string SqlConnctionString { get; set; }   public SqlConnection conn { get; set; }   public SqlTransaction tran { get; set; }   /// <summary>   /// 获得实体T所有数据   /// </summary>   /// <returns></returns>   public List<T> Select(T t)   {    List<T> list = new List<T>();    string sql = "select * from [" + t.TableName + "] WITH (NOLOCK) order by id desc";  //出于性能考虑,不用反射来获取表名    DataSet ds = SqlHelper.ExecuteDataset(SqlConnctionString, CommandType.Text, sql);    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)    {     list.Add(DataSetToEntity.DsToEntity<T>(ds, i));    }    return list;   }   /// <summary>   /// 根据主键ID获取数据(一条)   /// </summary>   /// <param name="id"></param>   /// <param name="TableName"></param>   /// <returns></returns>   public T SelectByID(int id, T t)   {    string sql = "select * from [" + t.TableName + "] WITH (NOLOCK) where ID=@ID"; //出于性能考虑,不用反射来获取表名    DataSet ds = SqlHelper.ExecuteDataset(SqlConnctionString, CommandType.Text, sql, new SqlParameter("@ID", id));    t = DataSetToEntity.DsToEntity<T>(ds, 0);    PropertyInfo[] prop = t.GetType().GetProperties();    return t;   }   /// <summary>   /// 插入新数据   /// </summary>   /// <param name="t">实体类</param>   /// <returns></returns>   public int Insert(T t)   {    try    {     Type mytype = t.GetType();     // 获取类的所有公共属性     System.Reflection.PropertyInfo[] pInfo = mytype.GetProperties();     string FieldName = "";//字段名称     string Values = "";//值     StringBuilder sql = new StringBuilder();     List<SqlParameter> paras = new List<SqlParameter>();     sql.Append("Insert into [");     sql.Append(mytype.Name);//数据库表名     sql.Append("](");     object[] objDataFieldAttribute = null;     foreach (System.Reflection.PropertyInfo pio in pInfo)     {      objDataFieldAttribute = pio.GetCustomAttributes(typeof(DataFieldAttribute), false);      if (objDataFieldAttribute != null && objDataFieldAttribute.Length > 0)      {       FieldName += ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + ",";       Values += "@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + ",";       paras.Add(new SqlParameter("@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName, pio.GetValue(t, null)));      }     }     FieldName = FieldName.TrimEnd(',');     Values = Values.TrimEnd(',');     sql.Append(FieldName);     sql.Append(") VAlUES (");     sql.Append(Values);     sql.Append(")");     int i = SqlHelper.ExecuteNonQuery(SqlConnctionString, CommandType.Text, sql.ToString(), paras.ToArray());     return i;    }    catch (Exception)    {     return -1;     throw;    }   }   /// <summary>   /// 更新数据   /// </summary>   /// <param name="t">需更新的实体类</param>   /// <returns></returns>   public int Update(T t)   {    try    {     int i = 0;     int primarykey = t.ID;     T oldT = t;     Type mytype = t.GetType();     System.Reflection.PropertyInfo[] pInfo = mytype.GetProperties();     oldT = SelectByID(primarykey, oldT);//获得原始值,为日志做准备     if (t != oldT)     {      string SetValue = "";//字段名称      string Where = " where ID=@ID";//值      StringBuilder sql = new StringBuilder();      List<SqlParameter> paras = new List<SqlParameter>();      sql.Append("Update [");      sql.Append(mytype.Name);      sql.Append("] Set ");      object[] objDataFieldAttribute = null;      foreach (System.Reflection.PropertyInfo pio in pInfo)      {       objDataFieldAttribute = pio.GetCustomAttributes(typeof(DataFieldAttribute), false);       if (objDataFieldAttribute != null && objDataFieldAttribute.Length > 0 && pio.GetValue(t, null).ToString() != pio.GetValue(oldT, null).ToString())       {        SetValue += ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + "=" + "@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + ",";        paras.Add(new SqlParameter("@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName, pio.GetValue(t, null)));       }      }      SetValue = SetValue.TrimEnd(',');      sql.Append(SetValue);      sql.Append(Where);      paras.Add(new SqlParameter("@ID", primarykey));      i = SqlHelper.ExecuteNonQuery(SqlConnctionString, CommandType.Text, sql.ToString(), paras.ToArray());      return i;     }     else     {      return -2;     }    }    catch (Exception)    {     return -1;     throw;    }   }   /// <summary>   /// 删除数据   /// </summary>   /// <param name="t"></param>   /// <returns></returns>   public int Delete(T t)   {    int i = 0;    int primarykey = t.ID;    Type mytype = t.GetType();    string TableName = mytype.Name;    string Where = " where ID =@ID";    string sql = "DELETE FROM " + TableName + Where;    try    {     i = SqlHelper.ExecuteNonQuery(SqlConnctionString, CommandType.Text, sql, new SqlParameter("@ID", primarykey));     return i;    }    catch (Exception)    {     return -1;     throw;    }   }   /// <summary>   /// 开始事务   /// </summary>   /// <returns></returns>   public void BeginTran()   {    try    {     conn = new SqlConnection(SqlConnctionString);     conn.Open();     tran = conn.BeginTransaction();    }    catch (Exception)    {     tran.Rollback();     conn.Close();     throw;    }   }   /// <summary>   /// 带事务的插入方法   /// </summary>   /// <param name="t"></param>   /// <returns></returns>   public int InsertByTran(T t)   {    try    {     Type mytype = t.GetType();     // 获取类的所有公共属性     System.Reflection.PropertyInfo[] pInfo = mytype.GetProperties();     string FieldName = "";//字段名称     string Values = "";//值     StringBuilder sql = new StringBuilder();     List<SqlParameter> paras = new List<SqlParameter>();     sql.Append("Insert into [");     sql.Append(mytype.Name);//数据库表名     sql.Append("](");     object[] objDataFieldAttribute = null;     foreach (System.Reflection.PropertyInfo pio in pInfo)     {      objDataFieldAttribute = pio.GetCustomAttributes(typeof(DataFieldAttribute), false);      if (objDataFieldAttribute != null && objDataFieldAttribute.Length > 0)      {       FieldName += ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + ",";       Values += "@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + ",";       paras.Add(new SqlParameter("@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName, pio.GetValue(t, null)));      }     }     FieldName = FieldName.TrimEnd(',');     Values = Values.TrimEnd(',');     sql.Append(FieldName);     sql.Append(") VAlUES (");     sql.Append(Values);     sql.Append(")");     int i = SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sql.ToString(), paras.ToArray());     return i;    }    catch (Exception)    {     tran.Rollback();     return -1;     throw;    }   }   /// <summary>   /// 带事务的更新方法   /// </summary>   /// <param name="t"></param>   /// <returns></returns>   public int UpdateByTran(T t)   {    try    {     int i = 0;     int primarykey = t.ID;     T oldT = t;     Type mytype = t.GetType();     System.Reflection.PropertyInfo[] pInfo = mytype.GetProperties();     oldT = SelectByID(primarykey, oldT);//获得原始值,为日志做准备     if (t != oldT)     {      string SetValue = "";//字段名称      string Where = " where ID=@ID";//值      StringBuilder sql = new StringBuilder();      List<SqlParameter> paras = new List<SqlParameter>();      sql.Append("Update [");      sql.Append(mytype.Name);      sql.Append("] Set ");      object[] objDataFieldAttribute = null;      foreach (System.Reflection.PropertyInfo pio in pInfo)      {       objDataFieldAttribute = pio.GetCustomAttributes(typeof(DataFieldAttribute), false);       if (objDataFieldAttribute != null && objDataFieldAttribute.Length > 0 && pio.GetValue(t, null).ToString() != pio.GetValue(oldT, null).ToString())       {        SetValue += ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + "=" + "@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName + ",";        paras.Add(new SqlParameter("@" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName, pio.GetValue(t, null)));       }      }      SetValue = SetValue.TrimEnd(',');      sql.Append(SetValue);      sql.Append(Where);      paras.Add(new SqlParameter("@ID", primarykey));      i = SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sql.ToString(), paras.ToArray());      return i;     }     else     {      tran.Rollback();      return -2;     }    }    catch (Exception)    {     tran.Rollback();     return -1;     throw;    }   }   /// <summary>   /// 带事务的删除方法   /// </summary>   /// <param name="t"></param>   /// <returns></returns>   public int DeleteByTran(T t)   {    int i = 0;    int primarykey = t.ID;    Type mytype = t.GetType();    string TableName = mytype.Name;    string Where = "] where ID =@ID";    string sql = "DELETE FROM [" + TableName + Where;    try    {     i = SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sql, new SqlParameter("@ID", primarykey));     return i;    }    catch (Exception)    {     tran.Rollback();     return -1;     throw;    }   }   /// <summary>   /// 带事务和条件的删除方法   /// </summary>   /// <param name="t"></param>   /// <returns></returns>   public int DeleteByTran(T t, string where)   {    if (where.IndexOf("1=1") > 0)    {     return -1;    }    int i = 0;    string Where = "] where " + where;    string sql = "DELETE FROM [" + t.TableName + Where;    try    {     i = SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sql, null);     return i;    }    catch (Exception)    {     tran.Rollback();     return -1;     throw;    }   }   /// <summary>   /// 提交事务   /// </summary>   /// <returns></returns>   public void CommitTran()   {    try    {     tran.Commit();     conn.Close();    }    catch (Exception)    {     tran.Rollback();     conn.Close();     throw;    }    finally    {     tran.Dispose();     conn.Dispose();    }   }   /// <summary>   /// 回滚事务   /// </summary>   public void RollBackTran()   {    try    {     tran.Rollback();    }    catch (Exception)    {     throw;    }   }  } } View Code 

好了,整个ORM就写完了,这样我们数据处理的类就写完了!

三:Domain层

ORM写完后,因为不同的表可能在不同的库中,所以ZeroORM还不能直接拿来用,需要在上面隔离一层,我们这里选择最简单的方式,大牛勿喷。

首先写一个Repository基类(这里就不抽象类了),代码如下

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Zero.Domain.Abstract; using Zero.Infrastructure.IBase; namespace Zero.Domain.Concrete {     public class ConcreteBase<T> where T : IDataBase     {  public Zero.Infrastructure.Conntion.ZeroORM<T> DbHelper;  public ConcreteBase()  {      DbHelper = new Infrastructure.Conntion.ZeroORM<T>();  }  public string SqlConnctionString { get { return DbHelper.SqlConnctionString; } set { DbHelper.SqlConnctionString = value; } }  public List<T> GetAllList(T t)  {      List<T> ubiList = new List<T>();      ubiList = DbHelper.Select(t);      return ubiList;  }  public bool Insert(T t)  {      int i = 0;      i = DbHelper.Insert(t);      return i > 0;  }  public bool Update(T t)  {      int i = 0;      i = DbHelper.Update(t);      return i > 0;  }  public bool Delete(T t)  {      int i = 0;      i = DbHelper.Delete(t);      return i > 0;  }  /// <summary>  /// 带事务的插入方法  /// </summary>  /// <param name="t"></param>  /// <returns></returns>  public bool InsertByTran(T t)  {      if (DbHelper.tran == null)      {   DbHelper.BeginTran();      }      int i = DbHelper.InsertByTran(t);      return i > 0;  }  /// <summary>  /// 带事务的更新方法  /// </summary>  /// <param name="t"></param>  /// <returns></returns>  public bool UpdateByTran(T t)  {      if (DbHelper.tran == null)      {   DbHelper.BeginTran();      }      int i = DbHelper.UpdateByTran(t);      return i > 0;  }  /// <summary>  /// 带事务的删除方法  /// </summary>  /// <param name="t"></param>  /// <returns></returns>  public bool DeleteByTran(T t)  {      if (DbHelper.tran == null)      {   DbHelper.BeginTran();      }      int i = DbHelper.DeleteByTran(t);      return i > 0;  }  /// <summary>  /// 带事务和条件的删除方法  /// </summary>  /// <param name="t"></param>  /// <returns></returns>  public bool DeleteByTran(T t, string where)  {      if (DbHelper.tran == null)      {   DbHelper.BeginTran();      }      int i = DbHelper.DeleteByTran(t, where);      return i > 0;  }  /// <summary>  ///   /// </summary>  /// <param name="t"></param>  /// <returns></returns>  public void RollBackTran()  {      DbHelper.RollBackTran();  }  /// <summary>  ///   /// </summary>  /// <param name="t"></param>  /// <returns></returns>  public void BeginTran()  {      DbHelper.BeginTran();  }  /// <summary>  /// 提交事务 提交成功返回"";失败返回错误信息  /// </summary>  /// <returns>提交成功返回"";失败返回错误信息</returns>  public string CommitTran()  {      if (DbHelper.tran != null)      {   try   {       DbHelper.CommitTran();       return "";   }   catch (Exception e)   {       return e.ToString();       throw;   }      }      else      {   return "不存在可提交的事务";      }  }  /// <summary>  /// 根据主键ID查询结果,返回T  /// </summary>  /// <param name="id"></param>  /// <returns></returns>  public T SelectByID(string id, T t)  {      if (id != "")      {   return DbHelper.SelectByID(int.Parse(id), t);      }      else      {   return null;      }  }     } } View Code 

然后去写Repository类和IRepository接口

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Zero.Domain.Entities;  namespace Zero.Domain.Abstract {     public interface IUserRepository     {         User GetEntity();         IQueryable<User> Users { get; }     } }

实现类:

using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using Zero.Domain.Abstract; using Zero.Domain.Entities; namespace Zero.Domain.Concrete {  public class UserRepository : ConcreteBase<User>, IUserRepository  {   public User GetEntity()   {    return new User();   }   public IQueryable<User> BaseTitleTypes   {    get { return GetAllList(GetEntity()).AsQueryable(); }   }   public UserRepository()    : base()   {    SqlConnctionString = ConfigurationManager.ConnectionStrings["ZeroTest"].ConnectionString;//获取连接字符串   }  } } 

然后去数据库建表

MVC实战起步(一):一个简易框架的搭建

链接字符串的位置写的有点蠢,不过先这样做吧,一切已快速为目的

现在,所有的准备工作都做完了,开始测试一下数据交互是否有问题!

在Zero项目中建一个Index控制器

MVC实战起步(一):一个简易框架的搭建

MVC实战起步(一):一个简易框架的搭建

然后右键Index添加视图。先不做IOC解耦,引用Domain层和基础设施层。

添加如下代码

// // GET: /Index/ public ActionResult Index() {  UserRepository us = new UserRepository();  bool b =us.Insert(new Domain.Entities.User { UserName = "Ambre" });  if (b)  {   var ListEntity = from o in us.Users        select o;   return Json(ListEntity, JsonRequestBehavior.AllowGet);  }  else  {   return Content(b.ToString());  } } 

然后去改下路由设置

MVC实战起步(一):一个简易框架的搭建

启动项目

MVC实战起步(一):一个简易框架的搭建

好了,完成!下篇文章将写如何快速的将IOC应用到项目中,然后前端类似于EasyUi的grid控件如何编写。

谢谢大家,喜欢的话,点个赞,这可是我的处女文呢!

正文到此结束
Loading...