從零開始編寫本身的C#框架(6)——SubSonic3.0插件介紹(附源碼)

  前面幾章主要是概念性的東西爲主,向初學者們介紹項目開始前的一些知識與內容,從本章開始將會進入實操階段,但願跟着本系統學習的朋友認真按說明作好每一步操做(對於代碼最好是直接照着文檔內容在你的IDE中打一次出來,而不是使用複製粘貼),這樣對你理解後面的章節會有較好的幫助,若是你對我這種書寫方式有什麼建議或支持,也但願在評論中留言,謝謝你的支持。html

 

  SubSonic3.0簡介git

  SubSonicRob Conery用c#語言寫的一 個ORM開源框架,使用BSD軟件受權許可(The BSD 3-Clause License)。它是一個實用的快速開發框架,經過很是簡單的配置,以及附帶的T4模板,就能夠幫咱們生成功能強大的數據訪問層工具,讓開發人員遠離SQL語句的拼接,專一於業務邏輯的開發。github

  SubSonic3.0適合短、平、快的中小型項目開發,支持MsSql、MySql與SQLite三種數據庫,支持Linq和支持事務。對數據庫操做靈活,對生成的SQL語句會自動進行優化,雖然是ORM框架,但在性能上並無太大的損失。它上手容易,是一個很是棒的ORM開發框架。
sql

  3.0版本最大的缺點是框架未開發完善,對多表關聯查詢支持的不是很好,只支持一個多表關聯條件(複雜的多表關聯只能使用存儲過程或SQL語句拼接方式來實現);條件語句對In與Not In不支持(須要在數據層從新封裝處理才行);若是使用Redis緩存的話,存儲數據時對subsonic3.0生成的實體有兼容問題,須要作一次轉換封裝後才能使用。數據庫

  不過總的來講,這些缺點都是能夠克服的,在開發效率、二次開發、軟件維護上來講,優勢也是很是明顯的,請你們耐心學完本系列,你就能很容易的掌握SubSonic3.0這個開發利器。express

 

  SubSonic3.0安裝說明c#

  SubSonic3.0安裝練習相關附件下載緩存

 

  在MsSql中新建一個數據庫SubSonicTest,並設置好登錄賬號與密碼爲SubSonicTest。服務器

  運行下載包裏的「SQL語句.txt」文件裏的語句,生成數據表、記錄與測試用的存儲過程。併發

  

 

  建立一個空白解決方案

  

  在解決方案中建立一個空Web應用程序項目

  

  將SubSonic文件夾複製進項目文件夾中

  

  刷新項目就能夠看到隱藏的SubSonic文件夾

  

  打開Web.config,添加數據庫連接字串

  

  

<connectionStrings>
    <!-- 鏈接數據庫的字符串 -->
    <add name="procom" connectionString="server=.;Initial Catalog=SubSonicTest;uid=SubSonicTest;pwd=SubSonicTest"/>
  </connectionStrings>
View Code

 

  將Dll和SubSonic.Core複製到解決方案中

  

  添加SubSonic3.0項目(直接使用源碼項目,方便在使用時調試及修改)

  

  

  

  添加SubSonic.Core項目和Castle.Core.dll引用(大神TerryLee的博客裏有Castle 開發系列文章 有興趣的朋友能夠進去學習一下)

 

  

  

  

 

  將SubSonic包含進項目中

  

  若是你的數據庫名稱、賬號和密碼設置同面前要求同樣的話,T4模板將會直接運行生成相關實體類,若是設置不同的,請按下面要求來進行設置

  打開Settings.ttinclude配置文件

  

  

 

  設置好之後,選擇所有T4模板文件,運行生成代碼

  

  

 

  SubSonic3.0模板介紹說明

   本文只介紹附件中SubSonic文件夾模板(MsSql),不適用官方發佈的模板

文件名稱 說明
ActiveRecord.tt 按數據表生成對應名稱的類實體(Model),以及支持lambda表達式的各類經常使用函數(包括增、改、查、刪、Exists等)
Context.tt 生成經常使用公共模版函數:Select、Insert、Avg、Count、Max、Min、Variance、StandardDeviation、Sum、Delete、GetQuery、Update等
CreateModel.tt  新增模板(原SubSonic3.0沒有這個模板),主要功能是數據表生成對應名稱的類實體(Model),這是普通的類實體,不附任何多餘的內容(函數),主要用於存儲到Redis緩存或作C/S接口通信時轉Json使用。非必須項
EntityTable.tt 新增模板(原SubSonic3.0沒有這個模板,裏面的功能從Structs.tt模板中分離出來的),主要功能是可直接獲取數據表名稱與字段名稱,減小開發中硬編碼的存在
Settings.ttinclude 模版參數配置
SQLServer.ttinclude MsSql數據庫讀取、生成的相關配置
StoredProcedures.tt 生成存儲過程調用函數(本模板生成的函數調用存儲過程很是方便,詳情請關注例子)
Structs.tt 生成表結構模版,提供給SubSonic插件調用

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  SubSonic3.0使用例子

  點擊下載本文本例子的解決方案源碼

  以前發佈過《SubSonic3.0使用例子》,當時剛開始接觸寫得有點亂,如今從新整理一下,使用上面生成的類來進行操做,能夠在項目中直接運行。對於下面的例子,能夠直接在解決方案中Debug運行,查看運行結果,以加深理解,固然大部分功能在正式開發中不多使用,因此簡單瞭解一下就能夠了,只要會用Lambda,那麼後面相關章節介紹時你就會使用。

  下面例子只適用於本文所附帶的模板,特此說明

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Solution.DataAccess.DataModel;
using SubSonic.Linq.Structure;
using SubSonic.Query;

namespace SubSonicTest
{
    public partial class Test : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //-------------------------------------------------------------------------------
            // 新增記錄
            //-------------------------------------------------------------------------------
            var branch = new Branch();
            branch.DeptCode = SPs.P_Branch_GetMaxBranchCode(2, 1).ExecuteScalar() + "";
            branch.Name = "客服部";
            branch.Comment = "客戶售後服務維護部門";
            branch.ParentId = 1;
            branch.Sort = 7;
            branch.Depth = 2;
            //AddDate這個屬性不用賦值,ORM框架生成更新語句時會自動過濾該字段,更新時將會使用數據庫中設置的默認值
            //branch.AddDate = DateTime.Now;

            //保存進數據庫
            branch.Save();

            WriteLine("記錄添加成功,新增Id爲:" + branch.Id);


            //-------------------------------------------------------------------------------
            // 修改記錄
            //-------------------------------------------------------------------------------
            //從數據庫中讀出剛添加的記錄
            var branchModel = Branch.SingleOrDefault(x => x.Id == branch.Id);
            //也能夠用這個
            //var branchModel = new Branch(x => x.Id == branch.Id);
            //打印讀取出來的數據
            WriteLine(branchModel.ToString());

            //修更名稱爲「售後服務部」
            branchModel.Name = "售後服務部";
            //保存進數據庫
            branchModel.Save();

            //從新從數據庫中讀取出來並打印到輸出窗口
            WriteLine((new Branch(x => x.Id == branch.Id)).ToString());


            //-------------------------------------------------------------------------------
            // 判斷剛剛修改的記錄是否存在
            //-------------------------------------------------------------------------------
            if (Branch.Exists(x => x.Id == branch.Id))
            {
                WriteLine("Id爲" + branch.Id + "的記錄存在!");
            }
            else
            {
                WriteLine("Id爲" + branch.Id + "的記錄不存在!");
            }



            //-------------------------------------------------------------------------------
            // 刪除記錄
            //-------------------------------------------------------------------------------
            //刪除當前記錄
            Branch.Delete(x => x.Id == branch.Id);
            //也可使用這種方法刪除
            //branchModel.Delete(); 
            WriteLine("刪除Id爲" + branch.Id + "的記錄成功!");
            //除了上面兩種刪除方法外,還有好幾種其它方法,不過都不經常使用,這裏就不詳細羅列出來,你們若是有興趣能夠查看我以前發佈的博客


            //-------------------------------------------------------------------------------
            // 判斷剛剛刪除的記錄是否存在
            //-------------------------------------------------------------------------------
            if (Branch.Exists(x => x.Id == branch.Id))
            {
                WriteLine("Id爲" + branch.Id + "的記錄存在!");
            }
            else
            {
                WriteLine("Id爲" + branch.Id + "的記錄不存在!");
            }






            //-------------------------------------------------------------------------------
            // 使用類實體附帶的函數查詢
            //-------------------------------------------------------------------------------
            //查找出全部記錄——使用All()
            var list = Branch.All();
            foreach (var tem in list)
            {
                //打印到輸出窗口
                WriteLine(tem.ToString());
            }


            //查詢指定條件的記錄——使用Find()
            IList<Branch> il = Branch.Find(x => x.Id > 0);
            foreach (var tem in il)
            {
                //打印到輸出窗口
                WriteLine(tem.ToString());
            }


            //獲取第2頁記錄(每頁3條記錄)
            il = Branch.GetPaged("Id Desc", 2, 3);
            foreach (var tem in il)
            {
                //打印到輸出窗口
                WriteLine(tem.ToString());
            }


            //使用Id倒序排序,獲取第3頁記錄(每頁3條記錄)
            il = Branch.GetPaged("Id Desc", 3, 3);
            foreach (var tem in il)
            {
                //打印到輸出窗口
                WriteLine(tem.ToString());
            }



            //-------------------------------------------------------------------------------
            // 使用Select類查詢
            //-------------------------------------------------------------------------------
            //建立Select對象
            //var select = new Select();
            //顯示指定的列
            var select = new Select(new string[] { BranchTable.Id, BranchTable.Name, BranchTable.DeptCode });
            //指定查詢表
            select.From<Branch>();


            //運行完上面這條語句後,SQL已經生成出來了,你們在Debug狀態將鼠標指向select就能夠看到,往下繼續執行時,每添加一個屬性都會添加在生成的SQL語句中


            //添加查詢條件——Id大於2且編號頭兩位爲01的部門
            select.Where(BranchTable.Id).IsGreaterThanOrEqualTo(2).And(BranchTable.DeptCode).StartsWith("01");
            //查詢時括號添加例子
            //select.Openexpression_r().Where("").IsEqualTo(0).Or("").IsEqualTo(11).Closeexpression_r().And("").IsEqualTo(3);

            //設置去重複——SubSonic沒有去重複選項,須要本身手動修改Dll源碼
            select.Distinct(true);
            ////select.IsDistinct = true;

            //設置查詢數量
            select.Top("5");

            //添加排序——倒序
            select.OrderDesc(BranchTable.Sort);
            ////List<string> orderbyList = new List<string>();
            //orderbyList.Add(BranchTable.Sort + " Desc");
            //orderbyList.Add(BranchTable.Id + " Desc");
            //select.OrderBys = orderbyList;

            //設置分頁,獲取第一頁記錄(每頁10條記錄)
            select.Paged(1, 10);


            //執行查詢——返回DataTable
            var dt = select.ExecuteDataTable();
            if (dt != null && dt.Rows.Count > 0)
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    //打印到輸出窗口
                    WriteLine(dt.Rows[i][BranchTable.Id] + " " + dt.Rows[i][BranchTable.Name]);
                }
            }

            //執行查詢——返回List
            var bl = select.ToList<Branch>();
            foreach (var tem in bl)
            {
                //打印到輸出窗口
                WriteLine(tem.ToString());
            }


            //查詢總記錄數
            var recordCount = select.GetRecordCount();
            //打印到輸出窗口
            WriteLine("記錄數量:" + recordCount.ToString());

            //select提供了不少接口,能夠返回不少不一樣的數據,具體你們能夠根據需求來獲取
            //Select與SqlQuery 主要用於條件等屬性不肯定時拼接查詢,若是你們須要使用相關內容,能夠留意後面的章節源碼,我已將相關的功能封裝到一些類中了,你們能夠直接調用




            //-------------------------------------------------------------------------------
            // HotelDBDB查詢類的使用方式
            //-------------------------------------------------------------------------------
            //使用數據庫名稱+DB做爲名稱的類,能夠直接調用聚合函數
            var db = new SubSonicTestDB();
            //平均值
            WriteLine("平均值:" + db.Avg<Branch>(x => x.Id).Where<Branch>(x => x.Id < 10).ExecuteScalar() + "");
            //計算數量
            WriteLine("計算數量:" + db.Count<Branch>(x => x.Id).ExecuteScalar() + "");
            //計算合計數量
            WriteLine("計算合計數量:" + db.Sum<Branch>(x => x.Id).ExecuteScalar() + "");

            //最大值
            WriteLine("最大值:" + db.Max<Branch>(x => x.Id).ExecuteScalar() + "");
            //最小值
            WriteLine("最小值:" + db.Min<Branch>(x => x.Id).ExecuteScalar() + "");


            //-------------------------------------------------------------------------------
            // 存儲過程調用方法
            //-------------------------------------------------------------------------------
            //使用SPs.存儲過程名稱(參數1, 參數2, 參數3);就能夠調用存儲過程
            var obj = SPs.P_Branch_GetMaxBranchCode(1, 0).ExecuteScalar();
            WriteLine(obj + "");
            //可根據存儲過程返回的數據,調用不一樣的Execute來獲取
            //你們試試在SPs.P_Branch_GetMaxBranchCode(1, 2)後面.一下,就能夠看到不少調用接口,使用對應的接口能夠返回不一樣的內容





            //-------------------------------------------------------------------------------
            // 直接執行QueryCommand的方式
            //-------------------------------------------------------------------------------
            //獲取數據源——主要用於綁定鏈接的服務器,若是有多臺服務器多個數據庫時,可以使用不一樣的數據源來進行綁定查找
            var provider = SubSonic.DataProviders.ProviderFactory.GetProvider();
            //定義事務,給後面的事務調用
            var batch = new BatchQuery(provider);

            var sql = string.Format("select * from {0}", BranchTable.TableName);
            //例一,獲取影響記錄數
            QueryCommand qcommand = new QueryCommand(sql, provider);
            WriteLine(qcommand.Provider.ExecuteQuery(qcommand) + "");

            //例二,獲取DataTable
            var q = new SubSonic.Query.QueryCommand(sql, provider);
            var table = q.Provider.ExecuteDataSet(q).Tables[0];
            if (dt != null && table.Rows.Count > 0)
            {
                for (int i = 0; i < table.Rows.Count; i++)
                {
                    //打印到輸出窗口
                    WriteLine(table.Rows[i][BranchTable.Id] + " " + table.Rows[i][BranchTable.Name]);
                }
            }


            //例三,使用事務執行
            batch.QueueForTransaction(qcommand);
            batch.ExecuteTransaction();


            //例四,直接使用數據源執行
            provider.ExecuteQuery(qcommand);
            //-------------------------------------------------------------------------------



            //-------------------------------------------------------------------------------
            // Linq查詢方式
            //-------------------------------------------------------------------------------
            //Linq查詢方式
            var query = new Query<Branch>(db.Provider);
            var posts = from p in query
                        where p.DeptCode.StartsWith("0101")
                        select p;
            foreach (var tem in posts)
            {
                //打印到輸出窗口
                WriteLine(tem.ToString());
            }



            query = db.GetQuery<Branch>();
            posts = from p in query
                    where p.Id > 3 && p.Id < 6
                    select p;

            //獲取查詢結果1
            foreach (var tem in posts)
            {
                //打印到輸出窗口
                WriteLine(tem.ToString());
            }


            //獲取查詢結果2
            List<Branch> li2 = query.ToList<Branch>();
            foreach (var tem in li2)
            {
                //打印到輸出窗口
                WriteLine(tem.ToString());
            }


            //-------------------------------------------------------------------------------
            // Linq多表關聯查詢方法
            //-------------------------------------------------------------------------------
            //方法一
            var query5 = from p in Position.All()
                         join b in Branch.All() on p.Branch_Id equals b.Id
                         where b.DeptCode == "0101"
                         select p;
            foreach (var tem in query5)
            {
                //打印到輸出窗口
                WriteLine(tem.ToString());
            }


            //方法二
            var qry = (from p in db.Position
                       join b in db.Branch on p.Branch_Id equals b.Id
                       where b.DeptCode == "0101"
                       select new ListView
                          {
                              PositionName = p.Name,
                              BranchName = p.Branch_Name,
                              DeptCode = b.DeptCode
                          });


            foreach (var view in qry)
            {
                WriteLine(view.ToString());
            }




            //-------------------------------------------------------------------------------
            // 使用事務
            //-------------------------------------------------------------------------------
            //例一
            //從部門表中查詢出編號爲0102的Id、名稱與說明三列
            var query1 = new SubSonic.Query.Select(provider, BranchTable.Id, BranchTable.Name, BranchTable.Comment).From(BranchTable.TableName).Where<Branch>(x => x.DeptCode == "0102");
            //加入事務
            batch.QueueForTransaction(query1);

            //查詢部門編號爲0102且職位名稱後面兩個字爲主管的全部職位
            var query2 = new SubSonic.Query.Select(provider).From<Position>().Where<Position>(x => x.Branch_DeptCode == "0102").And(PositionTable.Name).EndsWith("主管");
            //加入事務
            batch.QueueForTransaction(query2);
            //運行事務,不返回任何信息
            batch.ExecuteTransaction();

            //例二
            batch = new BatchQuery();
            batch.Queue(query1);
            batch.Queue(query2);
            //執行事務,並返回數據
            using (IDataReader rdr = batch.ExecuteReader())
            {
                if (rdr.Read())
                {
                    //query1 results
                    for (int i = 0; i < rdr.FieldCount; i++)
                    {
                        WriteLine(rdr[i] + "");
                    }
                }
                //rdr.MoveNext();
                rdr.NextResult();
                if (rdr.Read())
                {
                    //query2 results
                    for (int i = 0; i < rdr.FieldCount; i++)
                    {
                        WriteLine(rdr[i] + "");
                    }
                }
            }



            //例三
            batch = new BatchQuery(provider);

            var query3 = from p in db.Branch
                         where
                            p.Id > 1 && p.Id < 10
                         select p;
            batch.Queue(query3);

            var query4 = from p in db.Position
                         where p.Branch_DeptCode == "0103"
                         select p;
            batch.Queue(query4);
            //執行事務,並返回數據
            using (var rdr = batch.ExecuteReader())
            {
                if (rdr.Read())
                {
                    //query1 results
                    for (int i = 0; i < rdr.FieldCount; i++)
                    {
                        WriteLine(rdr[i] + "");
                    }
                }
                //rdr.MoveNext();
                rdr.NextResult();
                if (rdr.Read())
                {
                    //query2 results
                    for (int i = 0; i < rdr.FieldCount; i++)
                    {
                        WriteLine(rdr[i] + "");
                    }
                }
            }


        }




        /// <summary>
        /// DeBug時,在輸出窗口打印出指定內容
        /// </summary>
        /// <param name="str">要在輸出窗口顯示的內容</param>
        private void WriteLine(string str)
        {
            System.Diagnostics.Debug.WriteLine(str);
        }


        //內部類
        class ListView
        {
            public string PositionName { get; set; }

            public string BranchName { get; set; }

            public string DeptCode { get; set; }

            public string ToString()
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("PositionName = " + PositionName + "\r\n");
                sb.Append("BranchName = " + BranchName + "\r\n");
                sb.Append("DeptCode = " + DeptCode + "\r\n");

                return sb.ToString();
            }
        }
    }
}
View Code

 

 

 

 

 版權聲明:

  本文由AllEmpty原創併發佈於博客園,歡迎轉載,未經本人贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接,不然保留追究法律責任的權利。若有問題,能夠經過1654937@qq.com 聯繫我,很是感謝。

  發表本編內容,只要主爲了和你們共同窗習共同進步,有興趣的朋友能夠加加Q羣:327360708 或Email給我(1654937@qq.com),你們一塊兒探討。

  更多內容,敬請觀注博客:http://www.cnblogs.com/EmptyFS/

相關文章
相關標籤/搜索