EF7 Code First Only-所引發的一些“臆想”


At TechEd North America we were excited to announce our plans for EF7, and even demo some very early features. This post will cover the announcements we made during the session. You can also watch the recorded session from TechEd (the EF7 content starts at 46:40). When watching the demos please bear in mind that this is a very early preview - not all the features shown are even submitted into the main code base yet.

以上文字說明來自:EF7 - New Platforms, New Data Stores

沒錯,微軟已經在北美發布了 EF7(應該只是演示、代碼甚至都未提交到版本庫),時間是 2014-05-19,而我卻前幾天才看到這篇文章,都過了大半年時間了,哎!

有時候程序員學習新技能,首先了解一下此技能的“性格”和“脾氣”,看適不適合自己,就像找對象一樣,不適合的話,霸王硬上弓是沒用的,那如果合適的話,就好好的了解她、善待她,而不要整天再去想一些其他的(見一個愛一個的不少),“紅杏出牆”的最后結果是:到頭來什么都沒得到。編程語言、編程技術等一些相關的東西,往往是更新速度很快,但也造成了一些“迷惑性”,就像你瞞着女朋友上街看美女一樣,守住自己的本心,適合自己,老婆不在多,一個就好。

言歸正傳,我個人覺得這次 EF7 的發布,就像之前的 ASP.NET vNext 發布一樣,是一個里程碑,或者說因為 ASP.NET vNext,所以 Entity Framework 必須要做一些適合“她”的改變,其實追溯到底,他們都是微軟下一代 ASP.NET 的組成部分,那 EF7 具體的改變是什么呢?她適不適合你呢?我們先來看一下兩個關鍵詞:

  • New Platforms(新平台):之前發布的 ASP.NET vNext,已經支持跨平台了,先試想一樣:單獨的 Entity Framework 應用程序可以運行嗎?或者說 Entity Framework 可以獨立存在嗎?答案當然是不可以,也就是說 Entity Framework 必須依附於某一類應用程序,比如 Windows Forms、ASP.NET 等,既然 Entity Framework 的“宿主”已經支持跨平台了,那 Entity Framework 就沒有不支持的道理,給力的一段話是:EF7 will work on all of these platforms as well as Mono, on both Mac and Linux. 請注意關鍵字“all”,聽起來是蠻激動人心的。
  • New Data Stores(新數據存儲):新數據存儲是什么?EF7 we will be enabling providers that target non-relational data stores,注意關鍵字“provider,non-relational”,難道是支持 NoSQL?但文中並沒有提到這個關鍵字,反而提到一個什么 Azure Table Storage?完全沒有聽說過,這個可以看作是微軟給自己打廣告,就像針對新平台的視頻演示中使用 Windows Phone 一樣,見怪不怪了。

因為之前 ASP.NET vNext 的發布,其實這兩點內容現在看來 EF7 也“理應如此”,但如果單純去看 Entity Framework 的發展歷程,你會發現這兩點改變是非常巨大的,以前的 Entity Framework 只是“循規蹈矩”做好 ORM 份內的工作就好,而這一次完全像脫胎換骨一樣,當然有人喜歡,也有人感覺討厭,除了上面講到的兩個改變關鍵詞,EF7 另一個改變就是:

這篇文章是前幾天無意看到的,本來是想翻譯一下分享出來的,但奈何英文功力實在太差,翻譯到一半就翻譯不下去了。Code First 不是我們第一次遇到,從 EF 4.1 版本,Entity Framework 就開始支持 Code First 了,以至於我們在現有 Entity Framework 的最新版本 6. 1 中,可以很好的使用 Code First 模式,當然你也可以使用 Database & Model First 模式,但在 EF7 中,請注意標題的關鍵字“Only”,也就是說 EF7 將只支持 Code First 模式,這是個什么概念呢?微軟到底想干嘛?

別激動,我們先來說下 Code First 的兄長-Database & Model First 模式,這也是我們使用 Entity Framework 的常用模式,我們開發一個應用程序,首先根據業務需求去設計表結構,當然這個工作是業務需求人員和 DBA 去完成的,和程序員相關不大,等數據庫表結構什么的確定下來以后,然后我們程序員就開始使用 Entity Framework 根據已有數據庫生成對應模型了,大致體現是:

如果在應用程序開發過程中,需求變更了,業務需求人員就會反饋至 DBA,DBA 就會根據業務需求變化修改表結構等,然后就對程序員說:XXX表結構已改。程序員收到數據庫修改完成指令后,就開始進行下面操作:

“從數據庫生成模型”后,我們針對原來模型寫的一些業務方法就必須要做出調整,然后我們就進行重寫,重寫,再重寫。。。

以上是我們使用 Database & Model First 模式的常規開發過程,我相信你肯定深有體會,畫了一個簡單示意圖:

這種模式可以很清楚的看到是以數據庫為核心,所有的程序設計、代碼編寫都是依賴於數據庫,數據庫一變,那什么都得跟着調整。在這個過程中,Entity Framework 變成了什么?我覺得僅僅是替代我們編寫 SQL 代碼的工具而已,並沒有發揮它的強大之處,ORM 中的 “O”,代表的是 Object(對象),但在這種模式開發的應用中,你會發現這些對象只不過是充滿屬性集合的類,我們做一些業務簡單的應用是可以的,但當開發一些業務極其復雜的應用,按照這種 Database & Model First 模式,大部分的業務都會寫在數據庫中,比如用存儲過程去實現,而對於程序員來說,只需要調用一個數據庫接口即可,那還不如直接寫 SQL 代碼來的方便,以至於 Entity Framework 在這種場景下變成了“雞肋”,我覺得在 EF7 之前的版本,是微軟對開發者做出的一種妥協,就像“從數據庫生成模型”這個方式一樣,只不過是微軟想把你從“事務腳本模式”拉出來,所做出的第一步,之后 EF4.1(開始支持 Code First)是第二步,現在的 EF7(僅支持 Code First)是第三步,這是最重要的一步,也是里程碑的一步,如果在上面應用場景中使用的是 EF7,那將會變成什么呢?請看下面示意圖:

你會發現,現在和之前的模式是完全“逆向”的,“Code First Only”模式代表着什么?說白了就是,如果你使用 EF7,那你就必須使用 Code First 模式,不要再想着“從數據庫生成模型”了,一切數據庫生成操作都必須體現在代碼中,這是你的工作,你可能覺得這種思想有點“迎合”領域驅動設計,其實從 EF 4.1 開始使用 Code First,我個人覺得微軟已經開始進行改變了,只不過現在改變的更加徹底,至於所蘊含的意義,只能意會了,我現在表達不出來,也許過幾年你會發現一切都是理所當然。

如果你使用 Entity Framework,並一直使用的是 Code First 模式,其實 EF7 帶給你的變化並不多(除了上面關鍵字的兩點),下面我簡單談一下我自己使用 EF Code First 的一般過程,當然也是我個人非常喜歡的,首先開發一個應用程序,我們一般先設計這個應用程序所存在的模型(Model),這個模型應該不受任何“污染”,也就是說它只是一個單純的模型,不要在上面加一些配置相關的東西,比如什么 Required、MaxLength 等屬性,這個應該是屬於數據存儲相關的東西,不應該在模型中存在,所以我們應該保持它的“純凈”,然后在模型中專注於業務的實現,這個其實就是領域驅動設計的部分體現,我想這也是以后應用程序開發的最普通過程,當然前提是以后(誰也說不准),貼一下示例模型代碼:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Age { get; set; }
    public string Address { get; set; }
    public DateTime DateAdded { get; set; }
    public virtual Role Role { get; set; }
}
public class Role
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime DateAdded { get; set; }
}

這段代碼胡亂摘自之前博文,模型中除了不要放配置相關的東西之外,還有一點就是,在設計對象關聯的時候,盡量用對象進行關聯,比如 User 中的 Role 屬性,如果在之前的設計中,肯定會設計成 RoleId,你如果覺得設計成 Role 對象屬性,那數據庫中該怎么存儲啊?其實如果你有這個想法,那你還是有點受“數據庫驅動模式”開發的影響,在模型中應該不要去關注數據存儲的一些東西,而應該把設計重點放在業務的實現上,這一點很重要,至於其他你所擔心的東西,Entity Framework 都會幫你完成,比如上面模型中,你不需要進行任何配置,使用 EF Code First,他會自動幫你生成相應數據庫,User 和 Role 的關聯,在數據庫中是用 RoleId 表示,但你發現 User 對象中並沒有 RoleId,而只有 Role 屬性,但當你使用 EF 獲取 User 對象,訪問其 Role 屬性的時候,你可以訪問到 Role 對象中的所有屬性,也就是說,你在寫代碼的時候,只需要關注模型的設計即可,其他的你不用關心,一切都有 Entity Framework 呢,至於模型內的一些操作都是對象之間的操作,就像現實生活中我與你對話一般。

另外,還需要提一點是,如果模型對象是多對多關系,比如上面的 User 和 Role,有可能是一個 User 擁有多個 Role,而一個 Role 也可能對應多個 User,那模型該怎么實現呢?其實很簡單:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Age { get; set; }
    public string Address { get; set; }
    public DateTime DateAdded { get; set; }
    public virtual IList<Role> Roles { get; set; }
}
public class Role
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime DateAdded { get; set; }
    public virtual IList<User> Users { get; set; }
}

我們分別給兩個對象加了兩個集合屬性,這也非常符合現實場景,那你所關心的數據庫該怎么實現呢?其實你使用 EF Code First 不需要任何配置,它會自動幫你生成三個表:User、Role 和 UserRole,具體關聯我就不說了,在對象訪問的時候,你會感受不到數據庫的“存在”,一切似乎都非常智能,說多了沒用,自己體會才是真理。

我喜歡的 Code First 模式是:模型是干凈的(不包含任何配置),也更智能化(用對象進行關聯),至於數據庫映射配置,可以單獨去實現,比如上面多對多關聯映射的自定義示例代碼:

    public class UserRoleDbContext : DbContext
    {
        public UserRoleDbContext()
            : base("name=UserRoleDb")
        {
            //this.Configuration.LazyLoadingEnabled = false;
        }

        public virtual DbSet<User> Users { get; set; }
        public virtual DbSet<Role> Role { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder
                .Configurations
                .Add(new UserConfiguration())
                .Add(new RoleConfiguration());
            base.OnModelCreating(modelBuilder);
        }

        public class UserConfiguration : EntityTypeConfiguration<User>
        {
            public UserConfiguration()
            {
                HasKey(c => c.Id);
                Property(c => c.Id)
                    .IsRequired()
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
                HasMany(t => t.Roles)
                    .WithMany(t => t.Users)
                    .Map(m =>
                    {
                        m.ToTable("UserRole");
                        m.MapLeftKey("UserId");
                        m.MapRightKey("RoleId");
                    });
            }
        }
        public class RoleConfiguration : EntityTypeConfiguration<Role>
        {
            public RoleConfiguration()
            {
                HasKey(c => c.Id);
                Property(c => c.Id)
                    .IsRequired()
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            }
        }
    }

EF7 符不符合我們的口味?它能給我們帶來什么?能改變我們什么?現在說的都是一些“空頭支票”,一切只能用時間來證明。

最后分享一個非常棒的文章,也存在我書簽很久了,作者是一個 MVP (關鍵是女的),我覺得她的一些想法和我有一些共鳴,詳細內容不說了,大家可以自行體會,關鍵詞:DDD、Entity Framework,文章鏈接:數據點 - 領域驅動設計的編碼:數據聚焦型開發的技巧


免責聲明!

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



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