.Net開發(fā)人員可以擁抱Entity Framework 了(EF4.3 Release!!!)
EF4.3于2月9號(hào)正式發(fā)布了,微軟的EF小組最近一年開始發(fā)力,在4.3版本中新加了重要的特性:“數(shù)據(jù)庫遷徙”。對于ORM框架來說,沒有Code First功能,幾乎沒有吸引力,因?yàn)楹苌匍_發(fā)人員會(huì)去用那些自動(dòng)生成的、難以駕馭的實(shí)體類,不夠優(yōu)雅。在Python等語言中的ORM框架,早就有了Code First的功能,而對于EF之前都是Databas First或者M(jìn)odel First,Code First在EF4中才出來,而且很不完善,其中最大的不足就是數(shù)據(jù)庫模型的維護(hù)比較麻煩,無法實(shí)現(xiàn)添加或者刪除實(shí)體的某些字段后,方便的更新數(shù)據(jù)庫中的表結(jié)構(gòu),需要開發(fā)人員花大量精力去維護(hù)數(shù)據(jù)庫結(jié)構(gòu)的升級(jí)以及保留歷史數(shù)據(jù),在開發(fā)過程中很不方便。 在這次的4.3版本中,數(shù)據(jù)庫遷徙功能終于是千呼萬喚始出來。微軟的產(chǎn)品有個(gè)特點(diǎn),早期很難用,但是越到后面越好用,慢慢的超過同類產(chǎn)品,所以對于.NET開發(fā)人員,我個(gè)人覺得是時(shí)候下功夫去深入學(xué)習(xí)并在實(shí)際項(xiàng)目中應(yīng)用EF了,我和我的團(tuán)隊(duì)已經(jīng)開始了。
閱讀目錄
1. 數(shù)據(jù)庫遷徙: 這是EF4.3中最重要的新特性,這樣我們就能將精力集中在程序員喜歡做的事情上:寫簡單傳統(tǒng)的CLR實(shí)體(Plain Old CLR Object),而不是寫SQL語句去維護(hù)數(shù)據(jù)庫,想添加一個(gè)字段就添加,想刪除就刪除,想修改名字就修改,是不是很爽?
2. 刪除了EdmMetadata表:這個(gè)表就是一個(gè)半成品,用CodeFirst根本不會(huì)用這個(gè)表去維護(hù)數(shù)據(jù)庫,因?yàn)橛辛藬?shù)據(jù)庫遷徙功能,數(shù)據(jù)庫的結(jié)構(gòu)信息能夠自動(dòng)生成,因此這個(gè)表就是多余的了。
3. 非Public字段上也可以添加數(shù)據(jù)描述屬性了:以前默認(rèn)情況下,Code First 會(huì)忽略private、protected和internal字段上的屬性信息,即使你寫代碼將這些字段包含到你的模型里面(通過Fluent API),這些字段上的屬性信息也會(huì)被忽略。在這個(gè)版本中,如果你通過Fluent API將這些非Public字段加入你的模型,所有屬性信息都能起作用了。
4. 能夠在配置文件中進(jìn)行更多的設(shè)置: 在App/Web.config 文件中能針對Code First方式進(jìn)行更多的配置,比如設(shè)置默認(rèn)的數(shù)據(jù)庫的Connection Factory和數(shù)據(jù)庫初始化器,甚至可以在配置文件中設(shè)置實(shí)體對象的構(gòu)造函數(shù)參數(shù)。更多的配置信息可以在官方博客中找到。
5. 修改了一系列的Bug,包括Unicode的DbSet名稱等等。
下載下面示例代碼
| 名稱 | 說明 |
| VS2010 | 因?yàn)橐肗uGet |
| NuGet | 數(shù)據(jù)庫遷徙用到了NuGet的命令行工具,NuGet是非常有用的工具,如果還沒有用過這個(gè)工具,可以百度一下,也可以去開源社區(qū)了解和學(xué)習(xí),最好升級(jí)到最新版本(我是1.6)。 |
| EF4.3 | 這個(gè)可以直接用NuGet,安裝并引用到你的項(xiàng)目中。如果你安裝過beta版本,相信你也會(huì)用NuGet的命令工具升級(jí): Update-Package EntityFramework |
軟件開發(fā)是一個(gè)迭代增量的過程,沒有人能夠一開始就完全設(shè)計(jì)好數(shù)據(jù)模型,因此對于Code First來說,最常見的開發(fā)場景是隨著功能需求不斷完善我們的數(shù)據(jù)模型。下面開始一步一步嘗試數(shù)據(jù)庫遷徙功能。在示例中我用Asp.net MVC3項(xiàng)目,首先新建一個(gè)項(xiàng)目,選擇空模板,默認(rèn)情況會(huì)引用一個(gè)EntityFramework,但很可能是4.1版本,刪除這個(gè)引用,我們用NuGet將4.3版本的EF引入MVC3中:

當(dāng)然你也可以通過命令行的方式(打開NuGet的Package Management Console,PMC):PM> Install-package EntityFramework
假設(shè)我們要建立的是一個(gè)網(wǎng)上書店,首先我們通過Code First建立我們的模型:
public class BookContext : DbContext
{
public DbSet<Book> Books { get; set; }
}
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public double Price { get; set; }
}
非常簡單的模型,下一步是在我們網(wǎng)站上使用這個(gè)模型,將書以列表的方式顯示出來,第一步添加HomeController:
public class HomeController : Controller
{
public ActionResult Index()
{
BookContext db = new BookContext();
db.Books.Add(new Book { Title = "Think in C++", Price = 59 });
db.SaveChanges();
return View(db.Books.ToList());
}
}
第二步添加對應(yīng)的View:
@model List<MigarationDemo.Models.Book>
@{
ViewBag.Title = "網(wǎng)上書店";
}
<h2>書店里面有以下書籍</h2>
<ul>
@{
foreach (var item in Model) {
<li>書名: @item.Title</li>
}
}
</ul>
然后F5,你就應(yīng)該在瀏覽器里面看到下面的結(jié)果:

我們什么也沒干,一個(gè)簡單的網(wǎng)站就完成了,是不是很神奇?我們甚至沒有配置數(shù)據(jù)庫連接字符串。這都是因?yàn)镋F設(shè)計(jì)的原則是“約定好于配置” (Convention Over Configuration),默認(rèn)情況下,EF找你本機(jī)上的SqlExpress數(shù)據(jù)庫,因?yàn)槲覚C(jī)器上有這個(gè)數(shù)據(jù)庫,所以EF就能自動(dòng)連接數(shù)據(jù)庫,然后根據(jù)上面的數(shù)據(jù)模型生成對應(yīng)的數(shù)據(jù)庫:
如果到這里,一切都正常,讓我們進(jìn)入正題,使用EF4.3中的Migaration功能:
第一步:修改我們的模型,由于新的需求,每本書還應(yīng)該有一個(gè)ISBN編號(hào):
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public double Price { get; set; }
public string ISBN { get; set; }
}
如果這時(shí)候,你按F5,運(yùn)行系統(tǒng),會(huì)出現(xiàn)非法操作異常:“The model backing the 'BookContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).” 提示我們,應(yīng)該進(jìn)行數(shù)據(jù)庫遷移。
很簡單,只需要在PMC中執(zhí)行下面3個(gè)命令:
1. Enable-Migrations
2. Add-Migration Book-ISBN (Book-ISBN是任意一個(gè)名稱標(biāo)記,用來標(biāo)記一個(gè)遷移點(diǎn))
3. Update-Database
如果執(zhí)行完上面三個(gè)命令,并且一切順利,恭喜你,數(shù)據(jù)庫升級(jí)完成,你應(yīng)該在項(xiàng)目里面看到:

并且數(shù)據(jù)庫已經(jīng)變成:

這時(shí)候F5,運(yùn)行系統(tǒng),應(yīng)該一切正常了,你可以嘗試在Controller中加入另外一條記錄,我加入了:
db.Books.Add(new Book {
Title = "Think in C++ Volumne Two: Practical Programming",
Price = 59,
ISBN = "978-7-111-17115-7"
});
因此看到的是:

到此為止,我們已經(jīng)一步一步完成了最簡單的數(shù)據(jù)庫遷徙/升級(jí), 在上面生成的Migarations文件夾中主要一個(gè)配置文件和一個(gè)數(shù)據(jù)庫遷移文件,數(shù)據(jù)庫遷移文件有兩個(gè)函數(shù),一個(gè)是Up,即升級(jí)數(shù)據(jù)庫,一個(gè)事Down,即回溯數(shù)據(jù)庫,去看看生成的代碼很容易理解它干了什么。
雖然EF能夠自動(dòng)根據(jù)數(shù)據(jù)模型生成對應(yīng)的數(shù)據(jù)庫結(jié)構(gòu),但是通常自動(dòng)生成的數(shù)據(jù)庫只是最基本的,通常我們需要設(shè)置更多的屬性。比如上面的Book數(shù)據(jù)模型,默認(rèn)的數(shù)據(jù)庫是以BookId這個(gè)主鍵建立索引,可是我們還希望以Title建立索引,這樣我們能夠快速的根據(jù)書名查找。另外,上面示例中,添加ISBN字段后,已經(jīng)有了的數(shù)據(jù)默認(rèn)是Null,這會(huì)在程序中引起不必要的麻煩,我們假設(shè)希望已有的記錄的ISBN是000-0-000-00000-0。
面對上面這些需求,我們首先通過下面命令新建一個(gè)遷徙:
Add-Migration IndexTitleAndDefault
在項(xiàng)目樹的Migrations文件夾下面會(huì)生成一個(gè)新的cs文件,我的是201202191349250_IndexTitleAndDefault.cs,注意前面時(shí)間戳?xí)灰粯印?/p>
然后修改生成的遷移文件:
public partial class IndexTitleAndDefault : DbMigration
{
public override void Up()
{
AlterColumn("Books", "Title", c => c.String(nullable: false,maxLength:100));
CreateIndex("Books", "Title", true,"Index_Title");
AlterColumn("Books", "ISBN", c => c.String(nullable: false, defaultValue: "000-0-000-00000-0"));
}
public override void Down()
{
DropIndex("Books", "Index_Title");
}
}
最后執(zhí)行命令:Update-Database,數(shù)據(jù)庫應(yīng)該建立了Title的索引,并且ISBN的默認(rèn)值是000-0-000-00000-0。
上面所有操作都是更新到最新的版本,但有時(shí)候我們希望數(shù)據(jù)庫能回溯到以前的版本,這在以前手動(dòng)維護(hù)數(shù)據(jù)庫時(shí)候是比較困難的,而EF4.3提供的數(shù)據(jù)庫變遷特性能很方便的進(jìn)行回溯:
只需要執(zhí)行Updat-Database命令的時(shí)候,加入–TargetMigration:"XXX" 參數(shù)即可,比如我們想回到第二步的版本,我們只需要執(zhí)行:
PM> Update-Database –TargetMigration:"201202190625099_Book-ISBN"
但是為了實(shí)現(xiàn)版本回溯,我們就得特別注意實(shí)現(xiàn)Down函數(shù),相當(dāng)于Down函數(shù)式Up函數(shù)的反函數(shù)。
另外執(zhí)行Update-Database命令的時(shí)候加入-Script參數(shù),這樣就不是直接修改數(shù)據(jù)庫結(jié)構(gòu),而是生成相應(yīng)的Sql腳本:
Update-Database -Script -SourceMigration:"aaa" -TargetMigration:"bbb"
如果不指定TargetMigration,就默認(rèn)是遷徙到最新的版本。
據(jù)微軟的開發(fā)團(tuán)隊(duì)透露,EF的下一個(gè)版本是EF5,微軟的版本號(hào)非常混亂,最開始EF是1.0,后來說要和.Net Framwork的版本號(hào)統(tǒng)一,所以直接就上到了EF4,現(xiàn)在.Net Framework的下一個(gè)版本是4.5,可是EF又要變成5了,他們在搞什么? 不管怎么樣,看這個(gè)勢頭,EF5還是很值得期待的,有可能有以下改進(jìn):
1. 支持枚舉類型
2. 性能將有很大提升
3. 改進(jìn)SQL語句的生成,目前EF生成的Sql語句會(huì)比較復(fù)雜,在下一版本中將可能改善。
如果你希望EF有什么功能,可以去他們的網(wǎng)站投票,雖然最后決定權(quán)在微軟Guy,但是你的一票可能會(huì)影響他們選擇先開發(fā)什么功能。
現(xiàn)在看來,EF正在成為一個(gè)優(yōu)秀的ORM框架,將能極大的提高程序員的開發(fā)效率,能夠?qū)⒊绦騿T從數(shù)據(jù)訪問層解脫出來,專注于業(yè)務(wù)邏輯層。當(dāng)然,要掌握好EF,需要更加深入的學(xué)習(xí),比如應(yīng)該了解它都有哪些約定,應(yīng)該了解一下它為我們生成的Sql語句,這樣有助于我們寫出高效的代碼。
posted on 2012-02-20 08:42 技術(shù)改變世界 閱讀(24107) 評(píng)論(70) 收藏 舉報(bào)
浙公網(wǎng)安備 33010602011771號(hào)