CodeFirst是EntityFramework 4.1后新增的一種映射方式,在這種方式下,開發人員只需要編寫代碼,由ORM框架自動動創建模型和數據庫,數據庫則可看作類似於XML一樣序列化的方式,非常簡潔(由於開發人員可以無需關心數據庫的具體結構,最初也有叫做CodeOnly的)。
下面就以一個簡單的例子演示一下如何使用CodeFirst。
一、用Nuget添加EntityFramework框架的引用。
二、編寫代碼
static void Main(string[] args)
{
using (var db = new BloggingContext())
{
// Create and save a new Blog
Console.Write("Enter a name for a new Blog: ");
var name = Console.ReadLine();
if (!string.IsNullOrEmpty(name))
{
var blog = new Blog { Name = name };
db.Blogs.Add(blog);
db.SaveChanges();
}
// Display all Blogs from the database
var query = from b in db.Blogs
orderby b.Name
select b;
Console.WriteLine("All blogs in the database:");
foreach (var item in query)
{
Console.WriteLine(item.Name);
}
Console.WriteLine("Press any key to exit...");
}
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
}
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}
這里和以前的一點區別就是增加了一個繼承自DbContext的BloggingContext對象,它表示數據庫對象,Blogs則是它的表。如果不關心數據庫的存儲方式大可以把它看作一個全局變量。
上述代碼是可以直接執行的,雖然這里沒有主動指定數據庫,但程序默認使用LocalDb或SqlExpress創建庫,因為我用的是VS2012,就使用了LocalDb創建了庫,並且生成的表的結構如下:
如下是CodeFirst映射數據庫的一些基本原則:
數據庫名:當沒有顯示設置數據連接的時候,默認的數據庫是:.\SQLEXPRESS。如果本地沒有SQLEXPRESS,EF會嘗試LocalDb ((localdb)\v11.0) .\SQLEXPRESS 這個數據庫包含在VS2012中。數據庫的名稱一般是DbContext的"命名空間.類名"
表名:表名默認為模型類名的復數形式,並且每個表都使用dbo構架創建。這里生成的就是dbo.Lodgings.
主鍵:Code First會默認將以類似Id結尾來命名的屬性當作主鍵,如ID,Id,本例中的DestinationId都自動設置為主鍵。如果該屬性是int類型,Code First會在數據庫中默認將該列設置為自增長。
數據類型:在SQL Server中,字符串默認映射成nvarchar(max),byte[]映射成varbinary(max),bool映射成bit,decimal映射成decimal(18, 2),float映射成float。同時因為bool,decimal,float等是值類型,不能為給他們分配Null值。所生成的數據庫會要求對應的列非空。如Lodgings表中的IsResort
外鍵:當CodeFirst檢測到一對多的映射時,會自動生成相應的外鍵關聯,這個下一節再介紹。
三、數據模型變化的處理
當我們的數據結構變化了后,就會出現數據模型和數據庫不一致的情況。此時運行則會出現如下異常:
未經處理的異常: System.InvalidOperationException: The model backing the 'BloggingContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
官方給的解決方案如下:Code First Migrations。不過,在開發過程中,由於數據結構變更是很常見的事情,按照這個方案來未免麻煩了點,很多時候我們是采用一種更加簡單粗暴的做法:
System.Data.Entity.Database.SetInitializer(new DropCreateDatabaseIfModelChanges<BloggingContext>());
把這句話放在程序的最開始。這樣,一旦檢測到數據庫有變更,則會重建整個數據庫。需要注意的時,由於重建數據庫會刪除所有的數據,過於霸氣。因此不要輕易用於正式版本,使用時最好用DEBUG的宏把它括起來。
四、部署到其它數據庫
雖然默認情況下會使用LocalDb或SqlExpress創建數據庫非常方便,但實際應用中往往會要把它部署到指定的數據庫中的,要指定數據庫也非常簡單,只需要在app.config中添加配置即可(原來產生的默認配置不用處理)。
<connectionStrings>
<add
name="BloggingContext"
providerName="System.Data.SqlClient"
connectionString="Server=.\SQLEXPRESS;Database=Products;Trusted_Connection=true;"/>
</connectionStrings>
這里一並給一個比較常用的MySql連接的示例:
<connectionStrings>
<add name="BloggingContext" providerName="MySql.Data.MySqlClient"
connectionString="server=192.168.10.10;User Id=admin;password=test;database=BloggingContext;" />
</connectionStrings>
需要注意的是,如果原來的數據庫存在的時候,往往會因為殘留的數據和自動映射的不一致而出現無法創建表或其它的異常,最好先把原有的數據庫給刪掉。
五、參考資料