首页 > 学院 > 开发设计 > 正文

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

2019-11-14 13:47:33
字体:
来源:转载
供稿:网友

一:引言

这仅仅是一个新手写给新手共同入门的博文!这是一个使用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控件如何编写。

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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表