吉特倉庫管理系統-ORM框架的使用

賀臣發表於2016-09-12

 

  最近在園子裡面連續看到幾篇關於ORM的文章,其中有兩個印象比較深刻<<SqliteSugar>>,另外一篇文章是<<我的開發框架之ORM框架>>, 第一個做的ORM是相當的不錯的,第二個也是相當的不錯, 至少在表面上看起來是這麼一回事。至於具體的用法和實踐我沒有深入的去測試過,所以也不便發表更多的意見,不過這種造輪子的精神我個人還是比較佩服的, 雖說有時候造輪子是閒的蛋疼的事情,但是如果你沒有早過輪子你也體會不到造輪子給你帶來的感官感受。目前比較受歡迎的ORM框架肯定是微軟系的 EF莫屬, 當然之前還出現過類似此種框架的Alinq,這也是相當的不錯,不過作者大神貌似不怎麼更新了。

 

  前不久開源了自己開發的吉特倉儲管理系統【開源地址:https://github.com/hechenqingyuan/gitwms , 有興趣可以加入群 88718955,142050808 或者本人QQ 821865130 交流】,其中也用到了ORM框架, 但是這個ORM框架不是市面上所見到的ORM框架,是自己開發的一套ORM框架,因為拉不上臺面所以也就沒有對外公開過,只是自己做專案的時候一直在用,經過多年的修改維護也算有所小成, 在個人開發的倉儲系統中成功應用,而且有著較高的穩定執行記錄。最近也在給小範圍內給有興趣開發倉儲系統的朋友培訓如何快速的開發倉儲系統, 今天這裡總結一下培訓中所講到的ORM框架。

 

  一. 為什麼會有這個框架

    當年沒有Linq to SQL , EF 等ORM框架的時候, 寫SQL也還是相當痛苦的一件事,市面上當時有MyBatis框架, 這個ORM是從java移植過來的,好不好用不過多的說, 褒貶不一。但是我個人用下來就是有一個很不爽的就是那個配置SQL,那個SQL的配置檔案超級特麼的多,多到節操都快碎了一地。後面上班公司又基於微軟企業庫做了一個類似的ORM框架, 這個也沒有改變其配置檔案的蛋疼本質,那個誰一怒為紅顏,我特麼的一怒差點撂挑子不幹了。痛定思痛我決定自己來改改這個狗日的配置檔案,最終有所成也就成了現在吉特倉儲系統中使用的Git.Framework.ORM 框架。

    之前也相關自己要做一款非常不錯的ORM元件,要支援MS SQL,MySQL,Oracle,Sqlce,Sqlite 等,不過也是真的嘗試過,不過我還是有點異想天開,後面做到了對SQL Server,MySQL,Oracle的支援, 終究覺得做的不是那麼好,所以也就堅持不下去了,做出來終究也是就是跟別人裝逼,後面放棄了對多資料庫的支援,只對SQL Server 進行了重點的支援(可能是我能力有限以及對整體結構規劃的缺失,導致對其他的資料庫支援性並不是那麼好),因為我只是自己用而且我的最終目的不是做一個ORM,而是針對某種業務型的專案來輔助支撐。

 

  二. ORM中資料庫指令碼配置問題

  <dataCommand name="Common.GetProceParam" database="GitWMS" commandType="Text">
    <commandText>
      <![CDATA[
          SELECT [SPECIFIC_CATALOG],[SPECIFIC_NAME],[ORDINAL_POSITION],[PARAMETER_MODE],[PARAMETER_NAME],[DATA_TYPE],[CHARACTER_MAXIMUM_LENGTH] 
        FROM [INFORMATION_SCHEMA].[PARAMETERS] 
        WHERE [SPECIFIC_NAME]=@SPECIFIC_NAME
          ]]>
    </commandText>
    <parameters>
      <param name="@SPECIFIC_NAME" dbType="String" direction="Input"/>
    </parameters>
  </dataCommand>
資料庫指令碼配置問題

  最初系統中所有的SQL語句都是通過以上方式來配置配置在配置檔案中,寫了一個比較牛逼的DataCommandManager類用於來解析讀取這些SQL, 這些配置都是快取的。並且直接轉化為了ADO.NET中的Command物件,只需要在使用的時候連線資料庫並且傳入引數執行就可以,這樣看起來並不錯。說好話這樣是挺爽的,SQL 不用硬編碼在C#程式碼中了,可以隨時在配置檔案中修改, 這是java中一直流傳的套路(不懂java,但是看到的現象是這樣的),專案越做越龐大問題就來了, 業務越來越複雜SQL越來越多,配置檔案多到沒法維護了,一個問題除錯都不知道從何處還是找起,即使在配置檔案命名規範上死下功夫仍然存在大量的問題,比如配置檔案name值是一樣的重複了,SQL寫重複了也沒辦法知道,除非你知道這個專案裡面的所有配置節點。

<dataCommand name="Common.GetProceParam" database="GitWMS" commandType="Text">

  這個配置節點中的name 是配置資料庫SQL的唯一鍵值, SQL的配置檔案多達上百個,這個name重複了有時候根本不知道從何處找起,也想過使用工具來查詢,但是這樣終究是效率不高的。難道我每次寫一個SQL都要查詢一下name是否存在,當然很多人也會說無所謂嘛,但是我個人覺得這個不應該是工作的重點,更加應該將重心放到業務上去。

 

  三. ORM 配置重複的SQL

<dataCommand name="Common.GetProceParam" database="GitWMS" commandType="Text">
    <commandText>
      <![CDATA[
          SELECT [SPECIFIC_CATALOG],[SPECIFIC_NAME],[ORDINAL_POSITION],[PARAMETER_MODE],[PARAMETER_NAME],[DATA_TYPE],[CHARACTER_MAXIMUM_LENGTH] 
        FROM [INFORMATION_SCHEMA].[PARAMETERS] 
        WHERE [SPECIFIC_NAME]=@SPECIFIC_NAME
          ]]>
    </commandText>
    <parameters>
      <param name="@SPECIFIC_NAME" dbType="String" direction="Input"/>
    </parameters>
  </dataCommand>



<dataCommand name="Sys.GetProceParam" database="GitWMS" commandType="Text">
    <commandText>
      <![CDATA[
          SELECT [SPECIFIC_CATALOG],[SPECIFIC_NAME],[ORDINAL_POSITION],[PARAMETER_MODE],[PARAMETER_NAME],[DATA_TYPE],[CHARACTER_MAXIMUM_LENGTH] 
        FROM [INFORMATION_SCHEMA].[PARAMETERS] 
        WHERE [SPECIFIC_NAME]=@SPECIFIC_NAME
          ]]>
    </commandText>
    <parameters>
      <param name="@SPECIFIC_NAME" dbType="String" direction="Input"/>
    </parameters>
  </dataCommand>
配置重複的SQL

  上面這個這兩個SQL一模一樣,只是name的值不一樣,當時多人開發導致你根本無法知道這個SQL是不是重複了,雖然這個對程式執行沒有什麼影響,但是終究是重複了。而且我幾乎不可能判斷SQL是不是有重複的。這個就存在一個相當坑爹的事情,要做這個事情還是要花費一點時間,但是沒有辦法公用,不說每個開發人員都會搞一套,但是這種重複的問題是的的確確存在的問題,我相信做MyBatis開發的肯定深有體會。

public List<ProceMetadata> GetMetadataList(string argProceName)
        {
            DataCommand command = DataCommandManager.GetDataCommand("Common.GetProceParam");
            command.SetParameterValue("@SPECIFIC_NAME", argProceName);
            List<ProceMetadata> list = command.ExecuteEntityList<ProceMetadata>();

            return list;
        }
操作配置檔案中的SQL語句

  以上是操作配置檔案中C#程式碼,其實也就比Ado.NET 方便那麼一點點,如果加上配置等操作完全不會比Ado.NET簡單。上面這種還是個別案例,上面這段SQL用的人估計不會很多,如果涉及到業務問題比如獲取某個使用者的資訊,這個時候技術人員溝通不暢那麼就極有可能出現重複的程式碼。再後來的接盤俠過來了怎麼辦,我該怎麼獲取使用者的資訊,寫了這麼多獲取使用者的資訊,以前的又不敢動那我再重新寫一個吧。

 

  四. ORM獲取使用者資訊

SELECT * FROM [dbo].[T_USER]

SELECT UserID,[Password] FROM [dbo].[T_USER]

SELECT UserID,UserName FROM [dbo].[T_USER]

SELECT UserID,UserName,Email FROM [dbo].[T_USER]
我要獲取使用者資訊?

  獲取使用者資訊偷懶的辦法,我們在查詢欄位的時候直接SELECT * FROM , * 萬用字元真是一個好東西,可以少些好多的程式碼,用起來就是爽。如果從業務和更加嚴謹的角度來說其實我們不建議使用 * 來查詢所有表欄位資訊。業務環境點要求:我要查詢使用者編號和使用者名稱,我要查詢使用者名稱,使用者編號,使用者郵箱,我要查詢使用者所有的屬性資料,我要查詢使用者..... ;  這種需求再正常不過了,假設我們不允許在所有環境下查詢所有的資料庫屬性欄位,根據上面的框架來開發的話,那的配置多少個SQL配置節點,我要寫多少個DataCommand,這還只是其中一個業務點,一個系統怎麼可能只有一個業務點。

 

  五. 資料欄位許可權如何處理

<dataCommand name="Common.GetProceParam1" database="GitWMS" commandType="Text">
    <commandText>
      <![CDATA[
          SELECT * FROM [dbo].[T_USER]
          ]]>
    </commandText>
    <parameters>
    </parameters>
  </dataCommand>
獲取所有使用者資料
<dataCommand name="Common.GetProceParam" database="GitWMS" commandType="Text">
    <commandText>
      <![CDATA[
          SELECT UserID,UserName FROM [dbo].[T_USER]
          ]]>
    </commandText>
    <parameters>
    </parameters>
  </dataCommand>
查詢使用者編號和使用者名稱
<dataCommand name="Common.GetProceParam" database="GitWMS" commandType="Text">
    <commandText>
      <![CDATA[
          SELECT UserID,UserName,IDCard FROM [dbo].[T_USER]
          ]]>
    </commandText>
    <parameters>
    </parameters>
  </dataCommand>
查詢使用者身份資訊

  在業務系統中有些是特別敏感的資訊,比如ERP系統中對價格控制,客戶能夠看到什麼價格,VIP看到什麼樣的價格,什麼級別的領導看到又是另外的價格,人就是這麼的坑爹! 我相信這是一個再普通不過的業務場景了,各種價格保持到不同的資料庫列中,很多人的做法就是先將資料查詢出來,然後在用程式碼將沒有許可權的資料隱藏掉,這個也是我個人的一般做法,那麼我們能不能在讀取資料的時候就控制呢,根據許可權查詢特定的欄位資訊。這個肯定不用多說肯定是可以的, 根據上面的這種ORM配置來做 就是上面三種型別的配置,好坑爹啊。

 

======================ORM就是一個坑爹貨啊,根本達不到快速開發效果===========================

 

 六.徹底一些 ORM

    以上的事情足夠蛋疼好久的,每天要花大量的體力勞動時間來配置這些SQL語句,我能不能在不改動原有的結構基礎上讓這些操作變得更加的簡單一些。這是得讓我們好好想想的事情,ORM框架的核心點在哪裡,那就是解決物件與資料庫之間的對映關係以及物件與物件之間的關聯關係。先不說DataCommand這個類,我們分析Ado.NET 運算元據庫的特點,幾個步驟就不說了。兩個核心點:(1) SQL語句並且帶有佔位符(可選) (2) 設定佔位符引數 , 仔細想想這兩個是有規律的,最起碼第二個規律很明顯,就是AddParamater() 我們完全可以使用引數的形式迴圈設定這些佔位符引數。

    SQL語句的規則稍微有點複雜:

    (1) 增: insert into table (欄位,欄位) values(值,值)

    (2) 刪: delete from table where 條件  

    (3) 改: update table set 欄位=值,欄位=值 where 條件

    (4) 查: select *(欄位) from table where 條件

    解決以上ORM的問題,那麼就是如何動態的去替換如上語句的關鍵字。 這裡動態很重要,我們需要動態的去設定動態列以及條件,避免硬編碼的去配置SQL語句,動態也就意味著不同的條件生成的SQL是不一樣的,不需要配置檔案窮舉這些SQL語句了。我想ORM框架的開發基本就是這個理吧,只要具體細節如何實現就看對語法的理解以及對框架的設計如何了。

 

  七. 先說對映的屬性

[TableAttribute(DbName = "GitWMS", Name = "TNum", PrimaryKeyName = "ID", IsInternal = false)]
    public partial class TNumEntity:BaseEntity
    {
        public TNumEntity()
        {
        }

        [DataMapping(ColumnName = "ID", DbType = DbType.Int32,Length=4,CanNull=false,DefaultValue=null,PrimaryKey=true,AutoIncrement=true,IsMap=true)]
        public Int32 ID { get;  set; }

        public TNumEntity IncludeID (bool flag) 
        {
            if (flag && !this.ColumnList.Contains("ID"))
            {
                this.ColumnList.Add("ID");
            }
            return this;
        }

        [DataMapping(ColumnName = "Num", DbType = DbType.Int32,Length=4,CanNull=false,DefaultValue=null,PrimaryKey=false,AutoIncrement=false,IsMap=true)]
        public Int32 Num { get;  set; }

        public TNumEntity IncludeNum (bool flag) 
        {
            if (flag && !this.ColumnList.Contains("Num"))
            {
                this.ColumnList.Add("Num");
            }
            return this;
        }

        [DataMapping(ColumnName = "MinNum", DbType = DbType.Int32,Length=4,CanNull=false,DefaultValue=null,PrimaryKey=false,AutoIncrement=false,IsMap=true)]
        public Int32 MinNum { get;  set; }

        public TNumEntity IncludeMinNum (bool flag) 
        {
            if (flag && !this.ColumnList.Contains("MinNum"))
            {
                this.ColumnList.Add("MinNum");
            }
            return this;
        }

        [DataMapping(ColumnName = "MaxNum", DbType = DbType.Int32,Length=4,CanNull=false,DefaultValue=null,PrimaryKey=false,AutoIncrement=false,IsMap=true)]
        public Int32 MaxNum { get;  set; }

        public TNumEntity IncludeMaxNum (bool flag) 
        {
            if (flag && !this.ColumnList.Contains("MaxNum"))
            {
                this.ColumnList.Add("MaxNum");
            }
            return this;
        }

        [DataMapping(ColumnName = "Day", DbType = DbType.String,Length=50,CanNull=true,DefaultValue=null,PrimaryKey=false,AutoIncrement=false,IsMap=true)]
        public string Day { get;  set; }

        public TNumEntity IncludeDay (bool flag) 
        {
            if (flag && !this.ColumnList.Contains("Day"))
            {
                this.ColumnList.Add("Day");
            }
            return this;
        }

        [DataMapping(ColumnName = "TabName", DbType = DbType.String,Length=50,CanNull=false,DefaultValue=null,PrimaryKey=false,AutoIncrement=false,IsMap=true)]
        public string TabName { get;  set; }

        public TNumEntity IncludeTabName (bool flag) 
        {
            if (flag && !this.ColumnList.Contains("TabName"))
            {
                this.ColumnList.Add("TabName");
            }
            return this;
        }

        [DataMapping(ColumnName = "CompanyID", DbType = DbType.String,Length=50,CanNull=false,DefaultValue=null,PrimaryKey=false,AutoIncrement=false,IsMap=true)]
        public string CompanyID { get;  set; }

        public TNumEntity IncludeCompanyID (bool flag) 
        {
            if (flag && !this.ColumnList.Contains("CompanyID"))
            {
                this.ColumnList.Add("CompanyID");
            }
            return this;
        }

}
對映的實體物件

  老生常談的問題,實在不好意思在拿出來討論了,不說細節了可以去參考別人的ORM框架或本人的<<.NET ORM>>系列文章,在吉特倉儲管理系統中充斥著大量的這樣實體物件,應該說貫穿到了整個系統中。

[DataMapping(ColumnName = "CompanyID", DbType = DbType.String,Length=50,CanNull=false,DefaultValue=null,PrimaryKey=false,AutoIncrement=false,IsMap=true)]

  ColumnName是對映的列與屬性之間的關係,這個是核心也是關鍵,還有一個就是IsMap 這個屬性 這個表示是否對映欄位。為了靈活性我當然可以擴充套件這個實體類,但是我就是不想和資料庫欄位建立關係,你想怎樣。 

  一個實體物件對映一張表, 程式碼中我可以擴充套件這個實體物件屬性,這些屬性是和表之間唯一對應的,但是我是可以在查詢的時候連線查詢欄位或者計算出來的欄位做對映關係的,我就說了查詢是SQL中最難的。增刪改在操作的時候都必須和對應的表欄位對應,而查詢偏偏不是這樣的,我查詢可以從其他表關聯查詢出來,我可以取別名,我可以查詢自定義新的列, 物件是否處理,那關鍵就是看IsMap 這個值了。

  實體上有DataMapping 特性標識,說明和資料有對映關係,如果沒有則和資料庫對映操作沒有關係,資料庫無論怎麼操作都不影響這些資料。 標識IsMap=true的屬性 這個是和資料庫欄位強制關聯的(一般用於增刪改), 沒有這個值預設是false,這個時候查詢也會對映到此類屬性上.

 

  八. 定義了一套語法規則

public partial interface ITNum : IDbHelper<TNumEntity>
{
}
資料庫表操作介面
public partial class TNumDataAccess : DbHelper<TNumEntity>, ITNum
    {
        public TNumDataAccess()
        {
        }

    }
資料庫表操作實現

  傳說中的DbHelper, 之前還有人專門寫過一篇關於DbHelper的文章,到底要不要叫DbHelper, 我不想談論此類文章,畢竟我不是搞技術研究的料。此DbHelper 並非傳統的DbHelper類,這個是自己改良過的(並非改良,是完全不一樣,只是名字相同而已), 深受DDD領域驅動設計的毒害,每個人都這麼搞我也就弄了一個似於上面的倉儲模式,我水平低你們不要笑話我,我也不知道這個DDD中的倉儲是不是正宗的,只是看起來有點像,我此等超低領悟能力的人有點理解不來。因為我看到網上的.NET 相關的文章 DDD倉儲模型都是使用EF實現的,千篇一律沒有其他之一。

  在系統中我同樣會定義很多類似於上面的空的介面和空的實現實現類,基本每個表回對應一個這種模型,如果表很多該怎麼辦,你懂得, 做程式的雖然不聰明但是也絕對不會傻逼到每個都手寫。

public int AddMeasure(MeasureEntity entity)
{
            entity.IncludeAll();
            int line = this.Measure.Add(entity);
            return line;
}
新增一個實體物件

  在實體新增的時候,會將資料保持到實體對應的表中去,其中可能大家比較關注的是哪個IncludeAll() , 這個就是解決上面的指定指定問題的, IncludeAll() 意味著新增的時候會生成所有的欄位插入到表中。

entity.Include(alias => new { alias.MeasureName, alias.MeasureNum });

  這段程式碼表示在表中只新增兩個欄位,IncludeAll() 是新增所有的欄位. 當然如果你在新增的時候資料庫設計必填而你沒有包含進去,這個時候執行SQL的時候是會報錯的。

entity.Include("MeasureName").Include("MeasureNum");

  鏈式表示式,上面的這段程式碼和表示式這段程式碼是等價,在操作新增的時候都是包含了兩個欄位。只要能夠和欄位對映的上,你就可以無限次的包含欄位關係。

INSERT INTO [dbo].[Product]([SnNum],[BarCode],[ProductName],[Num],[MinNum],[MaxNum],[UnitNum],[UnitName],[CateNum],[CateName],[Size],[Color],[Standard],[Pressure],[GasketFace],[SCH],[Status],[ProcessMode],[Material],[InPrice],[OutPrice],[AvgPrice],[NetWeight],[GrossWeight],[Description],[PicUrl],[IsDelete],[CreateTime],[CreateUser],[StorageNum],[DefaultLocal],[CusNum],[CusName],[SupNum],[SupName],[Display],[Remark],[CompanyID]) 
VALUES(@SnNum,@BarCode,@ProductName,@Num,@MinNum,@MaxNum,@UnitNum,@UnitName,@CateNum,@CateName,@Size,@Color,@Standard,@Pressure,@GasketFace,@SCH,@Status,@ProcessMode,@Material,@InPrice,@OutPrice,@AvgPrice,@NetWeight,@GrossWeight,@Description,@PicUrl,@IsDelete,@CreateTime,@CreateUser,@StorageNum,@DefaultLocal,@CusNum,@CusName,@SupNum,@SupName,@Display,@Remark,@CompanyID)

  你執行的SQL語句可以是這樣,當然你也可以這樣

INSERT INTO [dbo].[Product]([SnNum],[BarCode],[ProductName],[Num]) 
VALUES(@SnNum,@BarCode,@ProductName,@Num)

  該死的窮舉配置所有的SQL可能性,可以滾蛋了。

 

  九. 查詢關聯的欄位

    你的ORM框架支援載入子類集合麼,或者自動載入主表的資料麼。 NO NO NO, 你特麼的不要跟我提為什麼不載入字表的集合,別的框架都支援載入子類集合啊?? 好煩 好煩 這種問題。  個人縮寫的這個ORM框架的確是不支援自動載入子類集合的,第一 個人能力有限, 第二 做ORM就一定要載入子項麼, 我就單表操作不可以麼(這裡不是說只能操作一張表,是能夠連線查詢的,但是連線查詢出來的結果集也是一張表啊)。 你別傻了, 變通 變通 變通!

public override List<InventoryDetailEntity> GetOrderDetail(InventoryDetailEntity entity)
        {
            InventoryDetailEntity detail = new InventoryDetailEntity();
            detail.IncludeAll();
            detail.Where(a => a.OrderSnNum == entity.OrderSnNum)
                .And(a => a.CompanyID == this.CompanyID)
                ;

            ProductEntity product = new ProductEntity();
            product.Include(a => new { Size=a.Size, CateName = a.CateName, Standard = a.Standard, Pressure = a.Pressure, GasketFace = a.GasketFace, SCH = a.SCH, ProductStatus = a.Status, ProcessMode = a.ProcessMode, Material = a.Material, GrossWeight = a.GrossWeight });

            detail.Left<ProductEntity>(product, new Params<string, string>() { Item1 = "TargetNum", Item2 = "SnNum" });

            List<InventoryDetailEntity> list = this.InventoryDetail.GetList(detail);
            return list;
        }
左連線查詢的相關操作

    在上面的IsMap 屬性還記得麼,上面說到了他就是為了解決連線查詢中欄位不能匹配實體的問題(反正就是一個區分到底匹配不匹配). 這是使用這種實體模型的時候,我們要大量去擴充套件資料庫對映模型屬性, 有點違法了大家DDD說的資料庫模型,業務模型,資料傳輸模型等分離的原則,什麼原則我是不懂了,在有些人眼裡肯定是不倫不類了。

product.Include(a => new { Size=a.Size, CateName = a.CateName, Standard = a.Standard, Pressure = a.Pressure, GasketFace = a.GasketFace, SCH = a.SCH, ProductStatus = a.Status, ProcessMode = a.ProcessMode, Material = a.Material, GrossWeight = a.GrossWeight });

    這個左連線查詢出來的屬性欄位,肯定要在實體類InventoryDetailEntity 中有對應的屬性欄位了。

public partial class InventoryDetailEntity
    {
        [DataMapping(ColumnName = "ProductName", DbType = DbType.String)]
        public string ProductName { get; set; }

        [DataMapping(ColumnName = "BarCode", DbType = DbType.String)]
        public string BarCode { get; set; }

        [DataMapping(ColumnName = "Size", DbType = DbType.String)]
        public string Size { get; set; }

        [DataMapping(ColumnName = "CateName", DbType = DbType.String)]
        public string CateName { get; set; }

        [DataMapping(ColumnName = "UnitName", DbType = DbType.String)]
        public string UnitName { get; set; }



        //擴充套件產品屬性

        [DataMapping(ColumnName = "Standard", DbType = DbType.String)]
        public string Standard { get; set; }

        [DataMapping(ColumnName = "Pressure", DbType = DbType.String)]
        public string Pressure { get; set; }

        [DataMapping(ColumnName = "GasketFace", DbType = DbType.String)]
        public string GasketFace { get; set; }

        [DataMapping(ColumnName = "SCH", DbType = DbType.String)]
        public string SCH { get; set; }

        [DataMapping(ColumnName = "ProductStatus", DbType = DbType.Int32)]
        public int ProductStatus { get; set; }

        [DataMapping(ColumnName = "ProcessMode", DbType = DbType.Int32)]
        public int ProcessMode { get; set; }

        [DataMapping(ColumnName = "Material", DbType = DbType.String)]
        public string Material { get; set; }

        [DataMapping(ColumnName = "GrossWeight", DbType = DbType.Double)]
        public double GrossWeight { get; set; }
    }
擴充套件屬性欄位

    可以和上面的那個實體物件做一下對比,DataMapping 也標識了,沒有那麼多屬性其實都是預設了,IsMap其實就預設了false,說明這些屬性和表Inventory 沒有直接的對應關係(記住一個宗旨,任何操作都可以看做是一個單表操作)。

 

  十. 如何解決上面提出的問題

    如果你還不能明白如何解決上述提出的問題,比如多配置,命名重複,許可權欄位等問題,那我只能說你還沒有明白我寫的文章,要麼就是我寫的文章太不入流了,不能讓你能夠很清楚的明白我的意思。

 

    我本身不是想做一個ORM框架,我就是想做了一個軟體,然後逐步的提高開發效率。其他人我不知道了,自從改進到目前的這個程度,在開發效率上的確提升很多了。自我感覺是良好的。 我深知這個ORM不能跟其他的ORM相比,看別人的ORM簡直就是高大上,我做這個ORM完全是為了解決當初的開發遇到的問題以及從自己做吉特倉儲系統業務的角度來出發的,所以在很大的程度上是有侷限性的。但是我相信在整個框架體系中(包括業務的設計)是可以在很大程度上彌補Git.Framework.ORM 方面的不足。

    技術是為業務服務,是為了解決問題,如果單純的只是為了做框架而框架,我並不覺得這是一個好的方式,就好比DDD領域驅動設計,這種設計思想是很好的,但是請別千篇一律的的找一個使用了DDD設計思想的技術框架奉為定律, 框架本身就是要靈活多變的,不同的業務體系框架也就會不一樣,架構也會不一樣。(恕我不懂DDD的精髓在此說了大話)

 

    以上程式碼實現在吉特倉儲管理系統中都有實現, 總體來說並沒有什麼技術門檻, 不要迷信這是一個非常好的框架,只是因為這個東西我就是為他而定製的,所以剛好就適應了它。如果有更多的想了解吉特倉儲管理系統,可以到github上去下載原始碼: https://github.com/hechenqingyuan/gitwms    有任何關於倉庫系統業務方面的也可以和我交流相互學習,最近也弄了兩次吉特倉儲管理系統快速開發培訓(小範圍的),如果有興趣的朋友,特別是上海的朋友可以近距離的交流吉特倉儲系統以及物流方面的知識。

 


作者:情緣
出處:http://www.cnblogs.com/qingyuan/
關於作者:從事倉庫,生產軟體方面的開發,在專案管理以及企業經營方面尋求發展之路
版權宣告:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。
聯絡方式: 個人QQ  821865130 ; 倉儲技術QQ群 88718955,142050808 ;
吉特倉儲管理系統 開源地址: https://github.com/hechenqingyuan/gitwms

相關文章