前兩回合,我們討論學習了如何采用Entity Framework在沒有數據庫的情況下自己寫一些實體類,然后通過CodeFirst反向生成對應的數據庫。通過CodeFirst,我們擺脫了edmx文件,沒有了繁瑣的Xml關系映射,使代碼變得無比的清晰,修改起來也變得更加容易。
在前兩篇文章中,我們的數據庫都是通過反向生成的,也就是說,屬於一個New Database(新數據庫),那么,對於一個Exist Database(已存在的數據庫),我們又應該怎么辦呢?本節文章,我們將對 Code First to an Existing Database 做出討論學習。
本回合我們將討論:
1、介紹使用“Entity Framework Power Tools“ 工具
2、EF CodeFirst to Existing Database 的快速入門
3、了解”Entity Framework Power Tools“ 工具為我們做了哪些事
案例代碼可以點擊這里下載
1、Entity Framework Power Tools 工具
在看完本節的導讀時,也許你已經有了自己的一點想法:“按照我的數據庫結構,自己手寫出一些對應的實體Model,然后再寫一個繼承自DbContext的上下文……”。沒錯,恭喜你,你的想法理論上確實是可行的,至少在表不太多的情況下是可行的。但是,如果這個數據庫的表有很多呢,數目已經達到了上百個或者更多呢?明顯的,我們如果想自己手寫實體和上下文,那無疑是一件巨大的工程。
既要懂得原理,也要懂得效率;我們要做某一件事,必須先要懂得它的原理,為什么要這么做,知其然知其所以然,所謂“原理先行”嘛。懂了了原理之后,我們需要提高效率,這在當今這個效率就是金錢的時代中尤為重要。
不扯開話題,下面我為大家介紹一款工具,它的名字就是:“Entity Framework Power Tools”,它的可以實現,對數據庫中已存在的表自動的生成相應的實體和上下文。這款工具的下載地址各位讀者可以點擊這里獲得最新版的下載。
各位讀者下載下來之后,雙擊打開安裝,然后再重啟Visual Studio實例,就可以使用啦。
2、快速入門(快速案例)
我們新建一個解決方案
再看看我們的數據庫,這里我采用上回合反向生成的數據庫(由於VS自帶的數據庫管理器用起來速度太慢,我額外裝了一個“SQL Server Management Studio”,數據庫實例還是采用原先的輕量級數據庫LocalDB,區別的僅僅是管理工具不同,數據庫實例還是一樣,各位讀者不必感覺疑惑)
右鍵點擊解決方案,我們發現了一些新東西
這就是我們剛才安裝的EF工具,順着點擊進去,我們會彈出一個SQL Server的連接窗口,填寫好相應的連接信息,點擊確定
稍等一會兒,系統會自動的連接數據庫,然后遍歷所有的表,並根據表結構生成一些代碼。
我們可以看到,解決方案中多了一個“Model”文件夾,里面包含有上下文、一些Model、“Mapping”文件夾以及其下的Map文件(映射文件)
我們先不解釋里面的東西,先在Program中寫調用代碼,解釋留到第三節再解析。
我們在Program中寫如下調用代碼:
class Program { static void Main(string[] args) { using (var db = new CodeFirst_2013_3_23BlogContextContext()) { Console.Write("Enter a name for a new blog:"); var name = Console.ReadLine(); var blog = new Blog { BlogName = name }; db.Blogs.Add(blog); db.SaveChanges(); var result = from b in db.Blogs select b; foreach (var item in result) { Console.WriteLine(item.BlogName); } } Console.ReadKey(); } }
F5,調試:
可以正常執行(上面那個小蝶驚鴻是上回合CodeFirst操作中遺留下來的數據)
3、EF工具幫我們生成了什么
上一節我們是一個快速入門,這一節我們看看EF Tool幫我們生成了些什么代碼。
先看一下App.config

<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <connectionStrings> <add name="CodeFirst_2013_3_23BlogContextContext" connectionString="Data Source=(localdb)\mydb;Initial Catalog=CodeFirst_2013_3_23.BlogContext;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" /> </connectionStrings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <parameters> <parameter value="v11.0" /> </parameters> </defaultConnectionFactory> </entityFramework> </configuration>
系統幫我們自動的填寫配置信息,值得注意的是“connectionStrings”節點,這里配置了EF的連接字串,在初始化上下文的對象時,上下文的構造函數會默認的傳入這里的連接字串。
<connectionStrings> <add name="CodeFirst_2013_3_23BlogContextContext" connectionString="Data Source=(localdb)\mydb;Initial Catalog=CodeFirst_2013_3_23.BlogContext;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" /> </connectionStrings>
進入“Model”文件夾
這里生成了一些實體類文件:
Post實體:

public partial class Post { public int PostID { get; set; } public string Title { get; set; } public string Content { get; set; } public int BlogID { get; set; } public virtual Blog Blog { get; set; } }
Blog實體:

public partial class Blog { public Blog() { this.Posts = new List<Post>(); } public int BlogID { get; set; } public string BlogName { get; set; } public string Url { get; set; } public virtual ICollection<Post> Posts { get; set; } }
Type實體:

public partial class Type { public int TypeID { get; set; } public string TypeName { get; set; } }
User實體:

public partial class User { public string UserName { get; set; } public string Display_Name { get; set; } }
還有上下文類CodeFirst_2013_3_23BlogContextContext:

public partial class CodeFirst_2013_3_23BlogContextContext : DbContext { static CodeFirst_2013_3_23BlogContextContext() { Database.SetInitializer<CodeFirst_2013_3_23BlogContextContext>(null); } public CodeFirst_2013_3_23BlogContextContext() : base("Name=CodeFirst_2013_3_23BlogContextContext") { } public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } public DbSet<Type> Types { get; set; } public DbSet<User> Users { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new BlogMap()); modelBuilder.Configurations.Add(new PostMap()); modelBuilder.Configurations.Add(new TypeMap()); modelBuilder.Configurations.Add(new UserMap()); } }
該上下文構造方法調用了父類DbContext的構造方法,傳入配置文件中的數據庫連接字串來連接需要的數據庫。
(反編譯DbContext得知其構造方法實際上是重載的方法,我們可以傳入多種的參數形式,這里我們不做過多的介紹)
最后,我們進入“Mapping”文件夾
里面包含的都是實體與數據庫,屬性與字段映射的關系文件,作用跟使用edmx文件時,那繁瑣的XML映射作用是一樣的,不過,采用CodeFirst方式生成的關系映射,代碼都是C#語言的,並且看起來相當清晰,以后重構起來也比edmx的XML方便得多。
至此,本回合的CodeFirst to Existing Database已經討論講解完畢,個人能力有限,可能文中會有錯漏的地方,歡迎各位朋友指正以及提出建議。