一個簡單得不能再簡單的“ORM”了

来源:http://www.cnblogs.com/deeround/archive/2016/07/14/5670891.html
-Advertisement-
Play Games

本文適合初學者,老鳥請點贊即走,謝謝。 文字功底有限,表述不恰當的地方,請各位多多包涵。 一,核心 現在ORM已經很多了,功能也齊全了,大家說我這是乾無聊的事,造的連車輪子都還不算,反正我就當學習。 還有就是,下麵這個不算正在的ORM,離真正在ORM差的很遠的。 主要思想 二,實例測試 1,基礎數據 ...


本文適合初學者,老鳥請點贊即走,謝謝。

文字功底有限,表述不恰當的地方,請各位多多包涵。

一,核心

      現在ORM已經很多了,功能也齊全了,大家說我這是乾無聊的事,造的連車輪子都還不算,反正我就當學習。

      還有就是,下麵這個不算正在的ORM,離真正在ORM差的很遠的。

      主要思想

      

二,實例測試

      1,基礎數據準備

          1.1 資料庫表結構(sqlite資料庫)

       

    1.2 實體

      

    public class Msg
    {
        public string Id { get; set; }
        public string Content { get; set; }
        public string Name { get; set; }
        public DateTime CreateTime { get; set; }
    }

   2,開始插入數據

    2.1 創建了一個控制台程式做測試

        string connStr = string.Format("Data Source={0};", System.AppDomain.CurrentDomain.BaseDirectory + "App_Data\\db.db");
            WangSql.ISqlExe sqlexe = new WangSql.SqlExe(WangSql.DbType.SQLLITE, connStr);

            string sql = "insert into Msg(Id,Content,Name,CreateTime) values(#Id#,#Content#,#Name#,#CreateTime#)";
            Msg model = new Msg()
            {
                Id = Guid.NewGuid().ToString("N"),
                Content = "這裡是內容",
                Name = "姓名",
                CreateTime = DateTime.Now
            };
            sqlexe.NonQuery(sql, model);

    查看下數據呢,

    

 

    至此,測試成功,再來測試下呢。

    2.2 開8個線程,每個線程迴圈插入100條數據試試看。

    測試結果:好尷尬sqlite多線程容易鎖庫,以後操作這個庫,還是隊列吧,樓主本著不放棄不拋棄的精神,再來了一次。

    

    這次沒被鎖,資料庫數據呢。

    

    數據也沒少,OK,測試完成。

 

三,源碼講解(準確的是代碼講解)

  3.1 生成SQL

    大家有沒有發現,我在執行時傳入sql的格式

 

    insert into Msg(Id,Content,Name,CreateTime) values(#Id#,#Content#,#Name#,#CreateTime#)//有沒有很熟悉呢,沒錯,就是借鑒(山寨)的ibatis的,哈哈

    就是這個樣子的,

    表:Msg(Id,Content,Name,CreateTime)

    DbDataParameter:values(#Id#,#Content#,#Name#,#CreateTime#)

    DbDataParameter,這裡支持值類型,string,object,object[],以及Hashtable和用戶自定義類。

    下麵就是生成SQL語句的代碼、

        public string SqlInit(string sql, out List<string> paraName)
        {
            string sqlTag = sql;
            List<string> sqlParaName = new List<string>();
            Regex regex = new Regex("(#(.[^#]+?)#)");
            var ms = regex.Matches(sql);
            foreach (Match item in ms)
            {
                var p1 = item.Groups[1];
                var p2 = item.Groups[2];
                sqlTag = sqlTag.Replace(p1.Value, prefix + p2.Value);
                if (!sqlParaName.Contains(p2.Value))
                    sqlParaName.Add(p2.Value);
            }
            paraName = sqlParaName;
            return sqlTag;
        }

    這個就會生成sql,並且還會把Parameter的key以集合的方式拋出去。

      3.2 實體轉成DbDataParameter

    當插入數據,參數傳入的是個用戶自定義類的話,需要做一次轉換。先將實體轉成Hashtable,然後再根據3.1生成sql拋出來的Parameter的key來生成Parameter集合。

    

        public static Hashtable ModelToHashtable(object model)
        {
            Hashtable ht = new Hashtable();
            BindingFlags flag = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            PropertyInfo[] propertys = model.GetType().GetProperties(flag);
            foreach (PropertyInfo pi in propertys)
            {
                string name = pi.Name;
                if (!pi.CanRead) continue;
                object value = pi.GetValue(model, null);
                ht.Add(name, value);
            }
            return ht;
        }

  3.3 完整NonQuery執行代碼

        public int NonQuery(string sql, object para)
        {
            if (IsModel(para))//Model入參
            {
                Hashtable ht = DataMapHelper.ModelToHashtable(para);
                List<string> paraName = new List<string>();
                string sqlTag = SqlInit(sql, out paraName);
                IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
                for (int i = 0; i < paraName.Count; i++)
                {
                    string key = paraName[i];
                    object value = ht[key];
                    sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
                }
                var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
                return result;
            }
            else if (para.GetType() == typeof(Hashtable))//Hashtanle入參
            {
                Hashtable ht = (Hashtable)para;
                List<string> paraName = new List<string>();
                string sqlTag = SqlInit(sql, out paraName);
                IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
                for (int i = 0; i < paraName.Count; i++)
                {
                    string key = paraName[i];
                    object value = ht[key];
                    sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
                }
                var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
                return result;
            }
            else if (para.GetType() == typeof(object[]))
            {
                List<string> paraName = new List<string>();
                string sqlTag = SqlInit(sql, out paraName);
                object[] ht = (object[])para;
                IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
                for (int i = 0; i < paraName.Count; i++)
                {
                    string key = paraName[i];
                    object value = ht[i];
                    sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
                }
                var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
                return result;
            }
            else//一個參數入參
            {
                List<string> paraName = new List<string>();
                string sqlTag = SqlInit(sql, out paraName);
                IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
                for (int i = 0; i < paraName.Count; i++)
                {
                    string key = paraName[i];
                    object value = para;
                    sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
                }
                var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
                return result;
            }
        } 

  3.4 查詢語句

     如果是查詢的話,執行完SQL返回一個DataTable,操作DataTable也太麻煩了吧,所以利用反射做了個實體轉換器。

     DataTable轉實體Model,DataRow轉實體Model,DataTable轉泛型T,DataRow轉泛型T (之前的文章)

    

        public static T DataRowToModel<T>(DataRow row)
        {
            T model;
            Type type = typeof(T);
            ModelType modelType = GetModelType(type);
            switch (modelType)
            {
                case ModelType.Struct://值類型
                    {
                        model = default(T);
                        if (row[0] != null)
                            model = (T)row[0];
                    }
                    break;
                case ModelType.Enum://值類型
                    {
                        model = default(T);
                        if (row[0] != null)
                        {
                            Type fiType = row[0].GetType();
                            if (fiType == typeof(int))
                            {
                                model = (T)row[0];
                            }
                            else if (fiType == typeof(string))
                            {
                                var value = Enum.Parse(typeof(T), row[0].ToString());
                                if (value != null)
                                    model = (T)value;
                            }
                        }
                    }
                    break;
                case ModelType.String://引用類型 c#對string也當做值類型處理
                    {
                        model = default(T);
                        if (row[0] != null)
                            model = (T)row[0];
                    }
                    break;
                case ModelType.Object://引用類型 直接返回第一行第一列的值
                    {
                        model = default(T);
                        if (row[0] != null)
                            model = (T)row[0];
                    }
                    break;
                case ModelType.Else://引用類型
                    {
                        model = System.Activator.CreateInstance<T>();//引用類型 必須對泛型實例化
                        #region MyRegion
                        //獲取model中的屬性
                        BindingFlags flag = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                        PropertyInfo[] modelPropertyInfos = type.GetProperties(flag);
                        //遍歷model每一個屬性並賦值DataRow對應的列
                        foreach (PropertyInfo pi in modelPropertyInfos)
                        {
                            if (!pi.CanWrite) continue;
                            //獲取屬性名稱
                            string tempName = GetFieldName(pi);
                            String name = string.IsNullOrEmpty(tempName) ? pi.Name : tempName;
                            if (row.Table.Columns.Contains(name) && row[name] != null)
                            {
                                ModelType piType = GetModelType(pi.PropertyType);
                                switch (piType)
                                {
                                    case ModelType.Struct:
                                        {
                                            var value = Convert.ChangeType(row[name], pi.PropertyType);
                                            pi.SetValue(model, value, null);
                                        }
                                        break;
                                    case ModelType.Enum:
                                        {
                                            Type fiType = row[name].GetType();
                                            if (fiType == typeof(int))
                                            {
                                                pi.SetValue(model, row[name], null);
                                            }
                                            else if (fiType == typeof(string))
                                            {
                                                var value = Enum.Parse(typeof(T), row[name].ToString());
                                                if (value != null)
                                                    pi.SetValue(model, (T)value, null);
                                            }
                                        }
                                        break;
                                    case ModelType.String:
                                        {
                                            var value = Convert.ChangeType(row[name], pi.PropertyType);
                                            pi.SetValue(model, value, null);
                                        }
                                        break;
                                    case ModelType.Object:
                                        {
                                            pi.SetValue(model, row[name], null);
                                        }
                                        break;
                                    case ModelType.Else:
                                        //throw new Exception("不支持該類型轉換");
                                        break;
                                    default:
                                        throw new Exception("未知類型");
                                }
                            }
                        }
                        #endregion
                    }
                    break;
                default:
                    model = default(T);
                    break;
            }

            return model;
        }

 

 

 

 

好了,差不多了吧,還有些多謝沒講,可以看我另外兩篇博客。

萬能的SqlHelper,麻麻再也不用擔心用什麼資料庫了

DataTable轉實體Model,DataRow轉實體Model,DataTable轉泛型T,DataRow轉泛型T

 

最後項目截圖吧,稍後源碼附上。

 

源碼下載:

 源碼下載

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在生產環境下麵對紛繁的業務處理場景,我們知道要處理很多邏輯代碼,其中有個叫枚舉(也稱窮舉),當處理這類事務時,會產生大量的迴圈執行,而迴圈是最耗CPU的,大量的迭代計算,可直接拉低計算速度,怎麼處理這類問題呢? 對於事務的不定項的選擇幾率,都會有一定的規律,比如說事件的概率發生,根據概率論的知識,我 ...
  • DMA(Direct Memory Access),直接存儲器訪問。DMA傳輸方式無需CPU直接控制傳輸,通過硬體為RAM與I/O設備開闢一條直接傳送數據的通路,使CPU效率大大提高。stm32f103有2個DMA控制器,DMA1有7個通道,DMA2有5個通道,專門用來管理來自外設對存儲器的訪問請求 ...
  • 1:打開任務管理器, [運行新任務] 2:(勾上以系統管理員許可權創建此任務) 輸入 cmd 3:進入要安裝的軟體所在的目錄:cd D:\111_安裝包\submit 3 (本文以安裝submit 為例子) 4:輸入命令:Sublime Text Build 3083 x64 Setup.exe 就會 ...
  • 定義這樣一個方法,然後接收前臺傳過來的值,調用這個方法就行了.. ...
  • 這篇文章我們開始看一下ActionFilter,從名字上其實就大概知道ActionFilter就是Action上的Filter,對吧,那麼Action上的Filter大概有幾個呢??? 這個問題其實還是蠻簡單的,因為我們聽說Mvc本身就是一個擴展性極強的框架,自然就是層層有攔截,層層有過濾,對吧,比 ...
  • 前言: 你先得知道HelpPageConfig文件,不知道說明你現在不需要這個,所以下文就不用看了,等知道了再看也不急.當然如果你很知道這個,下文也不用看了,因為你會了. 方法一: 方法二: 自定義一個支持從目錄載入xml文檔的XmlDocumentationProvider 使用方法: 使用方法: ...
  • 首個基於NHibernate的應用程式 Your first NHibernate based application 原文地址:http://www.nhforge.org/wikis/howtonh/your-first-nhibernate-based-application.aspx 本文涉 ...
  • 1. Tamcat 的安裝,此不介紹 路徑:F:\SolrTest\apache-tomcat-8.0.18 2. 解壓 solr 5.3.2 路徑:F:\Tool\solr-5.3.2 3. 複製solr5.3.2 webapp到tomcat 路徑:“F:\Tool\solr-5.3.2\serv ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...