C# ORM—Entity Framework 之Code first(程式碼優先)(二)
一、Entity Framework Code first(程式碼優先)使用過程
1.1Entity Framework 程式碼優先簡介
不得不提Entity Framework Code First這個介於牛A與牛C之間的功能,從4.1 開始的Code first使程式設計師,使軟體開發流程進入一個更加方便快捷的時代。
Code First是EntityFramework實現ORM的一種有利手段,因為傳統程式設計方式都是先建立資料庫,然後根據資料庫模型為應用程式建模,再進行開發;CodeFirst程式碼優先,先在程式中建立要對映到資料庫的實體結構,然後EntityFramework可以根據實體結構生成所對應的資料庫。
1.2 最新版本簡介(Entity Framework 5,現在VS2012中已出現EF6.0.0beta1版本了)
1.2.1 列舉支援是EF 久等的功能,並讓您在您的域類中擁有列舉屬性。EF5 讓列舉支援在 EF 設計器和Code First中是可用的。 1.2.2 現在,現有資料庫中的表值函式可以包含在使用 EF 設計器所建立的模型中。 1.2.3 可以使用DbGeography 和 DbGeometry 型別在模型中公開空間資料型別。空間資料可以包含在由EF 設計器或Code First所建立的模型中。 1.2.4 EF5 還包括一些重大的效能改進,Entity Framework 5相比EF4在效能上會有67%的提升 。使用這個版本EF的應用程式之所以效能提升,要部分歸功於LINQ to Entities查詢的自動編譯。自動編譯功能一直都是EF框架中的一部分,只是需要開發人員呼叫CompiledQuery.Compile才能夠使用。現在,EF 5會自動處理這步工作:當某個查詢首次執行時,它會被編譯並快取,從而使得後續請求可以避免重新完全編譯。EF 4為ESQL(嵌入式SQL)查詢使用了編譯後的查詢快取,而EF 5將該功能擴充套件到了LINQ to Entity查詢中。一旦緩衝中超過800個編譯後的查詢,某個回收演算法將開始生效並以每分鐘一次的週期清理快取。 實體依據LFRU(最近最早使用)原理從快取中移除。
1.3 Visual Studio 2012中的EF設計器,它也有一些新的功能:
1.3.1 現在模型可以被分為多個關係圖,在使用大型的模型時,這是很不錯的。您還可以應用著色到實體中來幫助您識別您的模型的分割槽。 1.3.2 改進了轉置模型的嚮導,使其更容易和更快地為查詢資料批量匯入儲存過程。
二、 Code First New Database使用
2.1 建立控制檯專案
2.2 新增引用最新的Entity Framework
專案上右鍵單擊—》管理NeGut程式包—》聯機,找到EntityFramework—》安裝 安裝之後即可看到packages.config
2.3 建立實體類
1 public class Blog 2 { 3 public int BlogId { get; set; } 4 public string Name { get; set; } 5 6 public virtual List<Post> Posts { get; set; } 7 } 8 public class Post 9 {10 public int PostId { set; get; }11 public string Title { get; set; }12 public string Content { get; set; }13 14 public int BlogId { set; get; }15 public virtual Blog Blog { get; set; }16 }View Code
2.4 建立資料上下文類
新增引用:using System.Data.Entity;並繼承DbContext
程式碼示例:
1 public class BlogContext : DbContext2 {3 public DbSet<Blog> Blogs { set; get; }4 public DbSet<Post> Posts { get; set; }5 }View Code
2.5 編寫測試程式碼
1 using (var db = new BlogContext()) 2 { 3 Console.WriteLine("輸入一個新的Blog名稱"); 4 var name = Console.ReadLine(); 5 6 var blog = new Blog { Name = name }; 7 db.Blogs.Add(blog); 8 db.SaveChanges(); 9 10 var query = from b in db.Blogs11 orderby b.Name12 select b;13 14 foreach (var item in query)15 {16 Console.WriteLine(item.Name);17 }18 }19 Console.ReadKey();View Code
以上便是最基本的應用
2.6 檢視資料庫
開啟SQL Server物件資源管理器,一般資料庫會建立在本機的開啟資料庫預設例項物件上
2.7 使用擴充套件
使用“程式包管理器控制檯”檢視、操作生成資料庫模型:開啟方式:工具—》庫程式包管理器—》程式包管理器控制檯(注意要選擇成您要操作的專案)
主要是資料庫遷移(增加實體類(資料表)、增加實體類欄位(資料庫欄位))
具體使用(開啟“程式包管理器控制檯”):
1. 輸入命令:Enable-Migrations 啟用Code first Migration;執行成功後會產生Migrations資料夾及兩個類:Configuration.cs 和<timestamp>_InitialCreate.cs,這是一個用時間戳作為字首的類。如201307080301469_InitialCreate.cs 注:如果不小心刪除了201307080301469_InitialCreate.cs這個檔案,可以使用Enable-Migration -Force重新建立
1.1 新增欄位:如在Blog內增加Url
1 public class Blog2 {3 public int BlogId { get; set; }4 public string Name { get; set; }5 public string Url { get; set; }6 7 public virtual List<Post> Posts { get; set; }8 }View Code
輸入命令:Add-Migration AddUrl,同時在Migrations下會有201307080524348_AddUrl.cs檔案 繼續輸入命令:Update-Database,更新資料庫
1.2 新增新的實體類檔案User
1 public class User2 {3 public string UserName { get; set; }4 public string DisplayName { get; set; }5 }
輸入命令:Add-Migration AddUser;(注可能提示沒有主鍵,此時要為表User建立主鍵,先新增引用:using System.ComponentModel.DataAnnotations;)
1 public class User2 {3 [Key]4 public string UserName { get; set; }5 public string DisplayName { get; set; }6 }
再次執行:Add-Migration AddUser;在執行Update-Database,檢視資料庫管理工具資料庫已建立
1.3 修改欄位
修改User實體類中的DisplayName為“display_name”在資料上下文類BlogContext中新增以下程式碼:
1 protected override void OnModelCreating(DbModelBuilder modelBuilder)2 {3 modelBuilder.Entity<User>()4 .Property(u => u.DisplayName)5 .HasColumnName("display_name");6 }
輸入命令:Add-Migration ChangeDisplayName ,在執行Update-Database,即可
1.4 刪除某一個欄位:刪除Blog實體類中的Url
首先在實體類中刪除此欄位
1 public class Blog2 {3 public int BlogId { get; set; }4 public string Name { get; set; }5 6 public virtual List<Post> Posts { get; set; }7 }
以上程式碼已刪除。 輸入命令:Add-Migration DeleteUrl ,之後在執行Update-Database即可。。
三、Code First An Existing Database使用(資料遷移功能暫時不能使用)
3.1 下載安裝擴充套件外掛
工具—》擴充套件和更新—》聯機,查詢“Entity Framework Power Tools”,進行下載,安裝,重新啟動。檢視是否安裝成功,工具—》擴充套件和更新—》已安裝,是否有此工具
3.2 新建資料表Blogs
1 CREATE TABLE [dbo].[Blogs] (2 [BlogId] INT IDENTITY (1, 1) NOT NULL,3 [Name] NVARCHAR (200) NULL,4 [Url] NVARCHAR(200) NULL, 5 CONSTRAINT [PK_dbo.Blogs] PRIMARY KEY CLUSTERED ([BlogId] ASC)6 );View Code
以及新建資料表Posts
1 CREATE TABLE [dbo].[Posts] ( 2 [PostId] INT IDENTITY (1, 1) NOT NULL, 3 [Title] NVARCHAR (MAX) NULL, 4 [Content] NVARCHAR (MAX) NULL, 5 [BlogId] INT NOT NULL, 6 CONSTRAINT [PK_dbo.Posts] PRIMARY KEY CLUSTERED ([PostId] ASC), 7 CONSTRAINT [FK_dbo.Posts_dbo.Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [dbo].[Blogs] ([BlogId]) ON DELETE CASCADE 8 ); 9 10 11 GO12 CREATE NONCLUSTERED INDEX [IX_BlogId]13 ON [dbo].[Posts]([BlogId] ASC);View Code
3.3 建立一個控制檯專案(名稱如:CodeFirstExistingDatabaseSample)
3.4 在專案CodeFirstExistingDatabaseSample上右鍵單擊—》選單中會有“Entity Framework”選項—》選擇Reverse Engineer Code First,輸入相應的資料庫地址,使用者名稱、密碼、要操作的資料庫等資訊,確定即可。(前提是要安裝好Power Tools 外掛)
3.5 資料遷移,此功估計EF還暫未實現,從使用工具Entity Framework Power Tools Betas3 以及使用的Entity Framework 6.0.0-beta1來看,估計這是EF 6.0的功能
四、資料庫生成位置可控制(其實主要就是DbContext的建構函式)
1.使用DbContext的建構函式:public DbContext(string nameOrConnectionString)
a、在app.config中新增:
1 <connectionStrings>2 <add name="CodeFirstBlogContext" providerName="System.Data.SqlClient" connectionString="Server=.;Database=CodeFirstBlog;uid=sa;pwd=sa" />3 </connectionStrings>
b、在資料上下文類中新增建構函式(原來沒有顯示出現,呼叫預設的一般是本機.\sqlexpress資料庫例項)
1 public BlogContext(string config)2 : base(config)3 {4 }
這裡可以顯示的引用配置檔案中的配置庫,注:此處config可以直接寫name=CodeFirstBlogContext,是配置檔案中的connectionStrings下的name。
2. 使用DbContext的建構函式:public DbContext(DbConnection existingConnection, bool contextOwnsConnection)
a、在資料上下文類中新增建構函式(原來沒有顯示出現,呼叫預設的一般是本機.\sqlexpress資料庫例項)
1 public BlogContext(DbConnection connection,bool contextOwnsConnection)2 : base(connection, contextOwnsConnection) 3 { }
b、使用時建立一個Connection即可
1 string connStr = "Server=.;Database=CodeFirstBlog2;uid=sa;pwd=sa"; 2 using (SqlConnection conn = new SqlConnection(connStr)) 3 { 4 using (var db = new BlogContext(conn, false)) 5 { 6 Console.WriteLine("輸入一個新的Blog名稱"); 7 var name = Console.ReadLine(); 8 9 var blog = new Blog { Name = name };10 db.Blogs.Add(blog);11 db.SaveChanges();12 13 var query = from b in db.Blogs14 orderby b.Name15 select b;16 17 foreach (var item in query)18 {19 Console.WriteLine(item.Name);20 }21 }22 }23 Console.ReadKey();View Code
3. 使用資料的連線工廠
1 Database.DefaultConnectionFactory = new SqlConnectionFactory(@"Server=.\sqlexpress;Database=CodeFirstBlog4;uid=sa;pwd=sa");2 using (var db=new BlogContext())3 {4 db.Database.Initialize(true);5 db.Blogs.Add( new Blog { Name = "test" });6 db.SaveChanges();7 }
注:這裡指定資料庫名稱無效,應該與Database的Initialize方法有關,待查證。
4.這裡還有其他的DbContext建構函式可用,可直接檢視DbContext類的實現。