LiteORM-For-DotNet,我的第一個開源庫……更新


這是一個DotNet輕量級ORM框架,解決C#.Net開發過程中重復繁瑣的數據庫CURD操作。

YEasyModel ORM 框架                                                                                                           

1YEasyModel 動態庫:

 項目工程引用YEasyModel.dll,將YEasyModel.xml復制到當前bin生成的目錄下,用於顯示接口、參數說明。

 

2ModelApp實體類(模型)生成工具:

 ModelApp.exe用於生成表、視圖、存儲過程實體類。

 

支持平台                                                                                                                                    

目標平台:.Net Framework4.0及以上

開發語言:C#;

目標數據庫:MS Sqlserver 2005及以上

前言                                                                                                                                            

因工作中接手的.net項目,源碼里面都用了動軟代碼生成的源碼做為數據庫操作類庫。其中,有些根本就沒有用到,今后也不會用到的冗余代碼——垃圾代碼。而每次如果有表結構修改,就得重新生成表實體/手動修改實體類,然后再修改代碼中實體類邏輯,再修改DAL(數據庫訪問層)的賦值代碼、sql字段、數據類型。

 

於是,產生一個想法,借鑒EF的理念,利用反射技術,用表實體去操作數據庫,做增、改、刪、查處理。並且,將表實體類更精細化標注,增加了字段名、主鍵、自增長、注釋【標題】、數據類型、長度的屬性標識,更有利於實體生成更優的sql腳本。

由此,通過反射技術把所有表CUDR操作的統一處理,以前修改了表結構,就得更新表實體類、修改邏輯代碼、修改DAL。現在,只需求更新表實體及對應的邏輯代碼就可以,不用再去維護DAL代碼,干掉那些每個DAL層中70%的代碼,達到精簡代碼,提高開發效率的目的。

有了這個想法,便開始了冗長的擼代碼,斷斷繼繼歷經兩個月的時間,終於完成了構想的雛形。然后,又花點時間去了解一下怎么玩github,把源碼庫傳到上面去。放出來,讓有需要的人拿去用,希望各位看官多多指教、發表意見,大家一起改進,完善。

下面奉上我的github地址,走過路過的都進來看看,給個Star就更好不過了。

 

詳情介紹                                                                                                                                                            

項目開源庫結構圖

 

 

 

一、YEasyModel

主要實體類反射類庫,定義實體類字段的數據類型、長度、主鍵等特性;定義CURD方法,查詢參數表達式、排序表達式。利用lambda定義查詢邏輯,生成sql過濾條件;查詢/更新字段定義,通過反射生成對應的Sql參數;排序邏輯定義,生成字段排序規則;DataTable與實體類轉換方法。

 

YEasyModel主要類庫說明:

 

1、YEasyModel.ModelDAL,數據庫增、刪、改、查操作工具類;

 

類方法說明:

 

 

//
        // 摘要:
        //     SqlDataAdapter批量更新
        //
        // 參數:
        //   modelList:
        //     列表實體
        //
        // 類型參數:
        //   T:
        //     表實體類
        //
        // 返回結果:
        //     返回更新影響的行數
        public static int BatchUpdate<T>(List<T> modelList);
       
        //
        // 摘要:
        //     刪除一條記錄
        //
        // 參數:
        //   keyValue:
        //     主鍵值
        //
        // 類型參數:
        //   T:
        //     表實體類
        public static int Delete<T>(object keyValue);
        //
        // 摘要:
        //     刪除一條記錄
        //
        // 參數:
        //   filter:
        //     查詢條件:lambda條件過濾表達式
        //
        // 類型參數:
        //   T:
        //     表實體類
        public static int Delete<T>(Expression<Func<T, bool>> filter);
        //
        // 摘要:
        //     執行sql腳本
        //
        // 參數:
        //   sqlScript:
        //     sql腳本
        public static int ExecuteSql(string sqlScript);
        //
        // 摘要:
        //     查詢當前主鍵是否已存在
        //
        // 參數:
        //   keyValue:
        //     主鍵值
        //
        // 類型參數:
        //   T:
        //     表實體類
        public static bool Exists<T>(object keyValue);
        //
        // 摘要:
        //     查詢當前字段值是否已存在
        //
        // 參數:
        //   filter:
        //     查詢條件:lambda條件過濾表達式
        //
        // 類型參數:
        //   T:
        //     表實體類
        public static bool Exists<T>(Expression<Func<T, bool>> filter);
        //
        // 摘要:
        //     查詢當前表最大的主鍵值
        //
        // 類型參數:
        //   T:
        //     表實體類
        public static object GetMaxID<T>();
        //
        // 摘要:
        //     根據主鍵值查詢獲取一條數據
        //
        // 參數:
        //   keyValue:
        //     主鍵值
        //
        // 類型參數:
        //   T:
        //     表實體類
        public static T GetModel<T>(object keyValue);
        //
        // 摘要:
        //     查詢當前字段值是否已存在
        //
        // 參數:
        //   filter:
        //     查詢條件:lambda條件過濾表達式
        //
        // 類型參數:
        //   T:
        //     表實體類
        public static int GetRecordCount<T>(Expression<Func<T, bool>> filter);
        //
        // 摘要:
        //     查詢當前指定字段的值
        //
        // 參數:
        //   filter:
        //     查詢條件:lambda條件過濾表達式
        //
        //   order:
        //     排序表達式
        //
        //   field:
        //     查詢字段:lambda字段表達式
        //
        // 類型參數:
        //   T:
        //     表實體類
        //
        // 返回結果:
        //     返回當前行的查詢字段值
        public static object GetValue<T>(Expression<Func<T, bool>> filter = null, OrderBy<T> order = null, Expression<Func<T, object>> field = null);
        //
        // 摘要:
        //     新增一條數據
        //
        // 參數:
        //   model:
        public static int Insert(object model);
        //
        // 摘要:
        //     新增一條數據
        //
        // 參數:
        //   model:
        //
        //   writeIdentityKey:
        //     是否寫入自增長ID
        public static int Insert(object model, bool writeIdentityKey);
        //
        // 摘要:
        //     多表聯合查詢(left join)
        //
        // 參數:
        //   joinExpression:
        //     聯接條件
        //
        //   filter:
        //     查詢條件
        //
        //   order:
        //     排序
        //
        //   fields:
        //     查詢字段
        //
        // 類型參數:
        //   T:
        //     返回的數據實體類型
        //
        //   T1:
        //     表1
        //
        //   T2:
        //     表2
        //
        // 返回結果:
        //     數據實體列表
        public static List<T> Join<T, T1, T2>(Expression<Func<T1, T2, bool>> joinExpression, Expression<Func<T1, T2, bool>> filter = null, OrderBy<T> order = null, params Expression<Func<T1, T2, object>>[] fields);
        //
        // 摘要:
        //     多表聯合查詢(left join)
        //
        // 參數:
        //   joinExpression:
        //     聯接條件
        //
        //   filter:
        //     查詢條件
        //
        //   order:
        //     排序
        //
        //   fields:
        //     查詢字段
        //
        // 類型參數:
        //   T:
        //     返回的數據實體類型
        //
        //   T1:
        //     表1
        //
        //   T2:
        //     表2
        //
        // 返回結果:
        //     數據實體列表
        public static DataTable JoinForDataTable<T, T1, T2>(Expression<Func<T1, T2, bool>> joinExpression, Expression<Func<T1, T2, bool>> filter = null, OrderBy<T> order = null, params Expression<Func<T1, T2, object>>[] fields);
        //
        // 摘要:
        //     獲取join聯接表
        //
        // 參數:
        //   parameters:
        //
        //   agrs:
        public static string JoinTable(ReadOnlyCollection<ParameterExpression> parameters, params Type[] agrs);
        //
        // 摘要:
        //     執行sql腳本查詢數據
        //
        // 參數:
        //   sqlScript:
        //     sql腳本
        //
        // 返回結果:
        //     DataSet
        public static DataSet Query(string sqlScript);
        //
        // 摘要:
        //     根據條件查詢
        //
        // 參數:
        //   filter:
        //     查詢條件:lambda條件過濾表達式
        //
        //   order:
        //     排序表達式
        //
        //   fields:
        //     查詢字段:lambda字段表達式【可多組】
        //
        // 類型參數:
        //   T:
        //     表實體類
        //
        // 返回結果:
        //     列表實體
        public static List<T> Select<T>(Expression<Func<T, bool>> filter = null, OrderBy<T> order = null, params Expression<Func<T, object>>[] fields);
        //
        // 摘要:
        //     根據條件查詢
        //
        // 參數:
        //   filter:
        //     查詢條件:lambda條件過濾表達式
        //
        //   order:
        //     排序表達式
        //
        //   fields:
        //     查詢字段:lambda字段表達式【可多組】
        //
        // 類型參數:
        //   T:
        //     表實體類
        //
        // 返回結果:
        //     列表實體
        public static DataTable SelectForDataTable<T>(Expression<Func<T, bool>> filter = null, OrderBy<T> order = null, params Expression<Func<T, object>>[] fields);
        //
        // 摘要:
        //     根據條件查詢一條記錄
        //
        // 參數:
        //   filter:
        //     查詢條件:lambda條件過濾表達式
        //
        //   order:
        //     排序表達式
        //
        //   fields:
        //     查詢字段:lambda字段表達式【可多組】
        //
        // 類型參數:
        //   T:
        //     表實體類
        //
        // 返回結果:
        //     列表實體
        public static T SelectSingleRecord<T>(Expression<Func<T, bool>> filter = null, OrderBy<T> order = null, params Expression<Func<T, object>>[] fields);
        //
        // 摘要:
        //     根據條件查詢第一條記錄
        //
        // 參數:
        //   topNumber:
        //     記錄數:默認1條記錄
        //
        //   filter:
        //     查詢條件:lambda條件過濾表達式
        //
        //   order:
        //     排序表達式
        //
        //   fields:
        //     查詢字段:lambda字段表達式【可多組】
        //
        // 類型參數:
        //   T:
        //     表實體類
        //
        // 返回結果:
        //     列表實體
        public static T SelectTopRecord<T>(int topNumber = 1, Expression<Func<T, bool>> filter = null, OrderBy<T> order = null, params Expression<Func<T, object>>[] fields);
        //
        // 摘要:
        //     SqlBulkCopy批量提交數據[復制]
        //
        // 參數:
        //   modelList:
        //     列表實體
        //
        // 類型參數:
        //   T:
        //     表實體類
        public static void SqlBulkCopy<T>(List<T> modelList);
        //
        // 摘要:
        //     更新一條數據
        //
        // 參數:
        //   model:
        //     數據實體
        //
        //   filter:
        //     過濾條件
        //
        //   fields:
        //     更新字段
        //
        // 類型參數:
        //   T:
        //     實體類型
        public static int Update<T>(T model, Expression<Func<T, bool>> filter, params Expression<Func<T, object>>[] fields);
        //
        // 摘要:
        //     根據主鍵更新一條數據
        //
        // 參數:
        //   model:
        public static int Update(object model);
View Code

 

2、YEasyModel.ModelUtil,數據表轉實體模型工具類; 

類方法說明:

        //
        // 摘要:
        //     DataRow數據行轉實體
        //
        // 參數:
        //   dr:
        //     DataRow數據行
        //
        // 類型參數:
        //   T:
        //     實體類
        //
        // 返回結果:
        //     單個實體
        public static T DataRowParse<T>(DataRow dr);
        //
        // 摘要:
        //     DataTable數據表轉實體列表
        //
        // 參數:
        //   dataTable:
        //     數據表
        //
        // 類型參數:
        //   T:
        //     實體類
        //
        // 返回結果:
        //     列表實體
        public static List<T> DataTableParse<T>(DataTable dataTable);
        //
        // 摘要:
        //     DataTable數據表轉實體
        //
        // 參數:
        //   dataTable:
        //     數據表
        //
        // 類型參數:
        //   T:
        //     實體類
        //
        // 返回結果:
        //     單個實體
        public static T DataTableParseSingle<T>(DataTable dataTable);
        //
        // 摘要:
        //     實體列表轉DataTable
        //
        // 參數:
        //   modelList:
        //     實體列表
        //
        // 類型參數:
        //   T:
        //     實體類
        public static DataTable ModelList2DataTable<T>(List<T> modelList);

3、YEasyModel.OrderBy,數據排序對象類;

類方法說明:

/// <summary>
        /// 添加字段排序
        /// </summary>
        /// <param name="field">字段表達式</param>
        /// <param name="orderByEnum">排序規則</param>
    public void Add(Expression<Func<T, object>> field, OrderByEnum orderByEnum)

/// <summary>
        /// 獲取字段排序表達式
        /// </summary>
        /// <returns></returns>
    public Dictionary<Expression<Func<T, object>>, OrderByEnum> GetOrderByList()

4、YEasyModel.ProcedureUtil,存儲過程調用工具類;

類方法說明:

//
        // 摘要:
        //     執行存儲過程
        //
        // 參數:
        //   model:
        public static int Execute<T>(T model);
        //
        // 摘要:
        //     執行存儲過程
        //
        // 參數:
        //   model:
        public static int Execute<T>(ref T model);
        //
        // 摘要:
        //     執行存儲過程-查詢數據
        //
        // 參數:
        //   model:
        public static DataTable Select<T>(T model);
        //
        // 摘要:
        //     執行存儲過程-查詢數據
        //
        // 參數:
        //   model:
        public static DataTable Select<T>(ref T model);

 

 

 

二、ModelApp

winform程序,用於配置連接數據庫,定義命名空間、實體類名,生成指定的表/視圖的實體模型;生成存儲過程實體模型,簡化存儲過程調用方式;

 

三、WebDemo

Webapi范例,簡單的表實體模型使用說明;

 

/******************************************使用示例******************************************/
            
               DBModel.Person_FaceInfoModel addModel = new DBModel.Person_FaceInfoModel()
                        {
                            //給字段賦值
                        };

                        //新增一條數據
            YEasyModel.ModelDAL.Insert(addModel);

                        //根據主鍵ID修改一條數據
            YEasyModel.ModelDAL.Update(addModel);

                        //修改一條數據,指定條件、更新字段
            YEasyModel.ModelDAL.Update<DBModel.Person_FaceInfoModel>(addModel, q => q.FaceID == 1);
            YEasyModel.ModelDAL.Update<DBModel.Person_FaceInfoModel>(addModel, q => q.FaceID == 1, q => q.FacePath, q => q.Remark);

            //根據ID查詢 Person_FaceInfoModel 對應表的所有記錄
            YEasyModel.ModelDAL.GetModel<DBModel.Person_FaceInfoModel>(id);

                        //查詢所有數據
            YEasyModel.ModelDAL.Select<DBModel.Person_FaceInfoModel>();

                        //根據FaceID查詢單條記錄
            YEasyModel.ModelDAL.SelectSingleRecord<DBModel.Person_FaceInfoModel>(q => q.FaceID == id);

                        //按條件查詢數據
            YEasyModel.ModelDAL.Select<DBModel.Person_FaceInfoModel>(q => q.Create_Date > DateTime.Now.AddDays(-1) 
                        && q.Create_Date < DateTime.Now && q.Remark != "");

                        //按條件查詢、指定字段1、字段2...
            YEasyModel.ModelDAL.SelectSingleRecord<DBModel.Person_FaceInfoModel>(q => q.FaceID == id, null, q => q.Person_ID, q => q.FacePath);

                        //創建字段排序規則
                        var order = new OrderBy<DBModel.Person_FaceInfoModel>();
                        order.Add(q => q.Create_Date, OrderByEnum.asc);
                        //查詢所有數據+排序
            YEasyModel.ModelDAL.Select<DBModel.Person_FaceInfoModel>(null, order, null);

            //刪除指定ID數據
            YEasyModel.ModelDAL.Delete<DBModel.Person_FaceInfoModel>(1);

                        //刪除指定條件的數據
            YEasyModel.ModelDAL.Delete<DBModel.Person_FaceInfoModel>(q => q.FacePath == "" && q.Remark == "");

            DataTable dt = new DataTable();//查詢數據
                        //DataTable數據轉實體列表
            YEasyModel.ModelUtil.DataTableParse<DBModel.Person_FaceInfoModel>(dt);

                        //DataRow數據轉實體                            YEasyModel.ModelUtil.DataRowParse<DBModel.Person_FaceInfoModel>(dt.Rows[0]);
    
            //調用存儲過程查詢CT_Comsume表最大ID
            DBModel.Proc.CT_Comsume_GetMaxIdModel proc = new DBModel.Proc.CT_Comsume_GetMaxIdModel();
            int iReturn = YEasyModel.ProcedureUtil.Execute<DBModel.Proc.CT_Comsume_GetMaxIdModel>(proc);

            //調用存儲過程刪除Detail_ID = 4的記錄
            DBModel.Proc.CT_ComsumeDetail_DeleteModel de = new DBModel.Proc.CT_ComsumeDetail_DeleteModel();
            de.Detail_ID = 4;
            int iReturn2 = YEasyModel.ProcedureUtil.Execute<DBModel.Proc.CT_ComsumeDetail_DeleteModel>(de);

            //多表join聯合查詢
            List<DBModel.Person_FaceInfoModel> person_FaceInfoModel = YEasyModel.ModelDAL.Join<DBModel.Person_FaceInfoModel, 
                DBModel.Person_FaceInfoModel, DBModel.ST_PersonModel>((t1, t2) => YEasyModel.SqlColumnUtil.IsNull(t1.Person_ID,0) == t2.Person_ID,(t1,t2)=>t1.Remark ==null,
                null,(t1,t2)=>t1.Person_ID, (t1, t2) => t1.Person_No, (t1, t2) => t1.FacePath);

 

(暫時先寫這些,后面有時間再完善)

 

性能                                                                                                                                                    

以下四種不同方式查詢數據庫記錄並轉為實體類的測試:

m1DataSet實體表查詢記錄;

m2YEasyModel實體類工具查詢記錄;

m3,三層工廠模式查詢記錄,實例化一次,后面從緩存取得實例;

m4Entity Framework查詢記錄;

查詢消耗的時間單位是毫秒。

 

第一次查詢1條記錄

 

 

 

第二次查詢1條記錄

 

 

 

第三次查詢1條記錄

 

 

  

第四次連續執行50次的查詢1條記錄

 

 

  

執行1次查詢8條記錄

 

 

  

連續執行50次的查詢8條記錄

 

 

  

根據以上多種測試結果對比得出:

m1 —— DataSet排第三;

m2 —— YEasyModel其次;

m3 —— 三層工廠模式最快,因為有實例化緩存,第二次開始便不用再創建實例對象, 單條數據查詢時,速度優勢明顯。但需要維護的邏輯代碼多;

m4 —— EF最慢,且劣勢明顯;太慢了!

測試代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using YEasyModel;

namespace WebApplication1.Tests
{
    static class Program
    {
        /// <summary>
        /// 應用程序的主入口點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            double m1 = 0;
            double m2 = 0;
            double m3 = 0;
            double m4 = 0;
            var c = new DBContext();
            var bll = new STCT.BLL.CT_DiningInfo();
            var aa = new DataSet1TableAdapters.CT_DiningInfoTableAdapter();
            for (int i = 0; i < 50; i++)
            {
                DateTime beforDT = System.DateTime.Now;
                DataSet1.CT_DiningInfoDataTable d = aa.GetData();
                DateTime afterDT = System.DateTime.Now;
                TimeSpan ts = afterDT.Subtract(beforDT);                
                var msg = string.Format("DataSet.GetModel總共花費{0}ms.    ", ts.TotalMilliseconds);
                m1 = m1 + ts.TotalMilliseconds;

                beforDT = System.DateTime.Now;
                List<CT_DiningInfo> mmm = ModelDAL.Select<CT_DiningInfo>();
                afterDT = System.DateTime.Now;
                ts = afterDT.Subtract(beforDT);
                msg += string.Format("ModelUtil.Select 總共花費{0}ms.    ", ts.TotalMilliseconds);
                m2 = m2 + ts.TotalMilliseconds;

                beforDT = System.DateTime.Now;
                var list = bll.GetModelList("");
                afterDT = System.DateTime.Now;
                ts = afterDT.Subtract(beforDT);
                msg += string.Format("STCT.BLL.CT_DiningInfo()總共花費{0}ms.    ", ts.TotalMilliseconds);
                m3 = m3 + ts.TotalMilliseconds;

                //beforDT = System.DateTime.Now;
                //var ssss = (from a in c.DBCT_DiningInfo select a).ToList();
                ////var ll = c.DBCT_DiningInfo.AsNoTracking().ToList();
                //afterDT = System.DateTime.Now;
                //ts = afterDT.Subtract(beforDT);
                //msg += string.Format("EF Linq 總共花費{0}ms.    ", ts.TotalMilliseconds);

                beforDT = System.DateTime.Now;
                //var ssss = (from a in c.DBCT_DiningInfo select a).ToList();
                var ll = c.DBCT_DiningInfo.AsNoTracking().ToList();
                afterDT = System.DateTime.Now;
                ts = afterDT.Subtract(beforDT);
                msg += string.Format("EF總共花費{0}ms.    ", ts.TotalMilliseconds);
                m4 = m4 + ts.TotalMilliseconds;

                Console.WriteLine(msg);
                Console.WriteLine();
            }

            Console.WriteLine(string.Format("m1:{0}.      m2:{1}.      m3:{2}.      m4:{3}", m1, m2, m3, m4));
            Console.WriteLine();

            Console.Read();
        }
    }
}

  

 

總結                                                                                                                                                   

(有空再寫)

最后,奉上github地址:https://github.com/michaelyes/LiteORM-For-DotNet


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM