你的位置:首页 > ASP.net教程

[ASP.net教程]MVC实战起步(一):一个简易框架的搭建


一:引言

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

二:项目分层

image

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

一: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;//获取连接字符串    }  }}

 

然后去数据库建表

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

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

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

image

image

然后右键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());   } }

 

然后去改下路由设置

image

启动项目

image

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

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