深度剖析Byteart Retail案例:基於MongoDB的倉儲實現

來源:互聯網
上載者:User

今天花了半天時間,向Byteart Retail案例加入了基於MongoDB的倉儲實現,讀者朋友可以直接從Byteart Retail的程式碼程式庫複製最新代碼來使用基於MongoDB的倉儲實現。

實現步驟1、重構ByteartRetail.Domain.Repositories目錄結構

本來這一步是不需要做的,但是因為之前沒有把結構規劃好,所以所有基於Entity Framework的倉儲實現都放在了根目錄下。現在把這些倉儲的實現都移到了EntityFramework目錄中,同時修改了命名空間和ByteartRetail.Services項目的web.config檔案。改完後結構如下:

2、實現基於MongoDB的倉儲和上下文

在《深度剖析Byteart Retail案例:倉儲(Repository)及其上下文(Repository Context)》一文中,我已經詳細介紹了Byteart Retail案例中倉儲及其內容相關的設計和實現,因此,在已有的架構上再實現一個MongoDB的倉儲是非常容易的事情,具體實現方式在此也不多做說明了,可以結合這篇文章並參考原始碼,整個過程只花了我不到一個小時的時間。實現後的目錄結構如下:

3、將SQL LocalDB中的資料移轉到MongoDB中

這部分花了我一些時間,為了簡單起見,我還是自己寫了一些控制台代碼,基本思路是:先用EntityFrameworkRepository將對象讀入,然後以彙總根為單位,使用MongoDBRepository依次寫入MongoDB。寫入的時候遇到了一些小問題,其中最需要注意的就是,在我們的SalesLine對象中彙總了SalesOrder,而SalesOrder本身又彙總了SalesLine,這就造成了循環參考,因此MongoDB會報錯的(EF不會報錯,因為EF採用了消極式載入功能來擷取SalesLine資訊),為瞭解決這個問題,需要配置MongoDB的Class Map,如下:

BsonClassMap.RegisterClassMap<SalesLine>(s =>{    s.AutoMap();    s.SetIgnoreExtraElements(true);    s.UnmapProperty<SalesOrder>(p => p.SalesOrder); // bypass circular reference.});

此外,我們需要用彙總根的ID作為MongoDB的objectID,並希望日期時間以本地時間格式儲存,因此,我另外開發了兩個Convention Profile,並在MongoDBRepositoryContext中增加了兩個靜態方法,以便應用程式在啟動的時候能夠調用這個靜態方法完成相關設定:

public class UseLocalDateTimeConvention : IMemberMapConvention{    public void Apply(BsonMemberMap memberMap)    {        IBsonSerializationOptions options = null;        switch (memberMap.MemberInfo.MemberType)        {            case MemberTypes.Property:                PropertyInfo propertyInfo = (PropertyInfo)memberMap.MemberInfo;                if (propertyInfo.PropertyType == typeof(DateTime) ||                    propertyInfo.PropertyType == typeof(DateTime?))                    options = new DateTimeSerializationOptions(DateTimeKind.Local);                break;            case MemberTypes.Field:                FieldInfo fieldInfo = (FieldInfo)memberMap.MemberInfo;                if (fieldInfo.FieldType == typeof(DateTime) ||                    fieldInfo.FieldType == typeof(DateTime?))                    options = new DateTimeSerializationOptions(DateTimeKind.Local);                break;            default:                break;        }        memberMap.SetSerializationOptions(options);    }    public string Name    {        get { return this.GetType().Name; }    }}public class GuidIDGeneratorConvention : IPostProcessingConvention{    public void PostProcess(BsonClassMap classMap)    {        if (typeof(IEntity).IsAssignableFrom(classMap.ClassType) &&             classMap.IdMemberMap != null)        {            classMap.IdMemberMap.SetIdGenerator(new GuidGenerator());        }    }    public string Name    {        get { return this.GetType().Name; }    }}public static void RegisterConventions(bool autoGenerateID = true, bool localDateTime = true){    RegisterConventions(autoGenerateID, localDateTime, null);}public static void RegisterConventions(bool autoGenerateID, bool localDateTime,     IEnumerable<IConvention> additionConventions){    var conventionPack = new ConventionPack();    conventionPack.Add(new NamedIdMemberConvention("id", "Id", "ID", "iD"));    if (autoGenerateID)        conventionPack.Add(new GuidIDGeneratorConvention());    if (localDateTime)        conventionPack.Add(new UseLocalDateTimeConvention());    if (additionConventions != null)        conventionPack.AddRange(additionConventions);    ConventionRegistry.Register("DefaultConvention", conventionPack, t => true);}
4、修改Global.asax.cs檔案

在Global.asax.cs檔案中,找到Application_Start方法,在這個方法中加入bootstrapper的調用:MongoDBBootstrapper.Bootstrap();。

當然,為了簡單起見,我還引入了一個MongoDBBootstrapper類,用來調用上面的RegisterConventions方法對Convention Profile進行註冊,同時還包含了對Class Map的註冊,在此就不貼代碼了。完成以上四步以後,準備工作就做好了。

啟用MongoDB倉儲及其上下文

準備工作做好以後,就讓我們開始啟用MongoDB倉儲吧。由於我上面已經完成了資料移轉,因此,在我的MongoDB資料庫中已經有了ByteartRetail資料庫。讀者朋友在完成最新版本程式碼複製品之後,請先自行安裝MongoDB服務,然後,在Byteart Retail原始碼目錄的demo_data目錄下,有個ByteartRetail.zip的壓縮包,將其解壓到你的本地磁碟,然後,進入MongoDB的bin目錄,使用mongorestore.exe程式恢複ByteartRetail資料庫。比如:

mongorestore -d ByteartRetail c:\ByteartRetail

完成資料庫恢複之後,你將可以在mongoDB的提示符下列出ByteartRetail資料庫:

下一步,修改ByteartRetail.Services下的web.config檔案,將unity配置部分中的Entity Framework倉儲及其內容相關的配置部分注釋掉,然後啟用MongoDB倉儲及其內容相關的配置,如下:

OK,現在啟動網站,從前台的角度我們基本上看不到任何變化,但此時Byteart Retail已經在使用MongoDB作為資料持久化機制了。

最後說明一下:如果你安裝MongoDB的時候不是使用的預設配置(比如你改過MongoDB的連接埠等設定),那麼,你可以修改ByteartRetail.Domain.Repositories.MongoDB.MongoDBRepositoryContextSettings 類,在這個類中根據你的具體情況對MongoDB進行配置。配置的詳細說明請參考該類中的注釋。

總結

本文也算是《深度剖析Byteart Retail案例》系列文章的一個題外篇,主要目的就是為了驗證在Byteart Retail案例中,倉儲及其內容相關的可擴充性。實驗證明,目前的架構設計能夠在不改動任何已有組件的基礎上,直接新增對其它資料持久化方案的支援,我們所要做的僅僅就是繼承幾個類、實現幾個介面,然後修改一下配置資訊。整個過程花了我一個人不到半天的時間,當然,Byteart Retail項目本身規模也不大,但仍然給了我們很好的啟示:良好的架構設計能夠大幅度降低團隊資源的浪費,並且減小出錯的幾率,同時還對系統運營提供了一定的支援:我們可以讓某個團隊單獨地開發一個組件,在完成開發與測試之後,可以在不大範圍影響系統啟動並執行基礎上將新的實現替換進去。因此,良好的架構設計將會對項目的管理帶來重大影響。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.