程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> MVC實戰起步(一):一個簡易框架的搭建,mvc實戰

MVC實戰起步(一):一個簡易框架的搭建,mvc實戰

編輯:C#入門知識

MVC實戰起步(一):一個簡易框架的搭建,mvc實戰


一:引言

這僅僅是一個新手寫給新手共同入門的博文!這是一個使用MVC,和一些主流框架(Autofac,Log4Net等)來完成的一個簡單的項目。和各位學習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;//獲取連接字符串
        }


    }
}

 

然後去數據庫建表

// // 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控件如何編寫。

謝謝大家,喜歡的話,點個贊,這可是我的處女文呢!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved