在任何框架中,對於數據庫的使用都是一個重點,因為我們使用的數據大部分都是存儲在數據庫中。ASP.NET MVC對數據庫提供了非常好的支持,尤其是當我們在開發中,可以使用實體框架(Entity Framework)進行代碼優先(Code-First)的開發工作。
所謂的代碼優先,需要和模型優先或數據庫優先一起討論。簡單點講,模型優先就是我們必須先設計model,然后通過模型生成數據庫的結構,數據庫優先就是我們在已有的數據庫上設計model。這樣的理解是很粗鄙的,但有關數據庫的討論需要很深厚的基礎知識作為儲備,鑒於本人的水平,這里不便展開。代碼優先是MVC"約定優於配置"的表現。所謂的"約定優於配置"是Ruby中擴散開來的概念,本質意義是我們可以將以前積累的經驗應用於框架中,使得我們以后開發沒有必要再配置每一項。使用代碼優先的方式,即使我們還沒有創建我們的數據庫,還是可以先創建我們的對象,也就是model,在創建的過程中,不用考慮數據庫中對象之間復雜的關系,不用添加任何有關數據持久層的標簽,這在實體框架識別主鍵的行為中發揮非常重要的作用。
要想使用這種開發方式,我們需要了解ASP.NET MVC提供的基架。基架是一個非常強大的工具,它可以為應用程序的CRUD(Create,Read,Update,Delete)生成所需要的樣板代碼。基架會根據model的定義,生成控制器以及該控制器的關聯視圖。簡而言之,基架可以為我們生成默認的模板,然后我們可以根據自己的需要進行修改。
因為基架,所以實體框架的使用更加強大。實體框架,顧名思義,就是一個對象關系映射框架。實體框架真的非常聰明,它知道我們的model中那個屬性是鍵值,即使我們沒有特意提醒。好吧,其實我們已經提醒了,就是我們的鍵值一般都是這樣的命名:XXID,其中XX為該model的名字,實體框架會自己假設該屬性為鍵值,並且賦給SQL Server對應的自動遞增鍵列。這些假設就是約定,只要我們在該框架下屬性的命名都遵從這種約定,那么,我們就可以享受這種便利。當然,EF對於外鍵,數據庫名稱等都有它的約定。
即使我們的數據庫是模擬的,但是我們也要創建它。創建一個模擬的數據庫,需要我們從EF的DbContext類中派生出一個類來訪問數據庫:
public class StoreContext : DbContext { public DbSet<User> Users { get; set; } public DbSet<Category> Categories { get; set; } public DbSet<Comment> Comments { get; set; } public DbSet<Log> Logs { get; set; } }
該派生類具有一個或多個DbSet<T>類型的字段,T是泛型,表示我們想要持久保存的對象。
接着我們只要將它new出來,結合LINQ就可以進行數據庫的各種操作,像是下面這樣的查詢:
User user = (from u in storeDb.Users where u.Name.ToLower() == User.Identity.Name.ToLower() select u).FirstOrDefault();
DbContext,顧名思義,就是數據上下文,在實際編程中,model有時候也會被修改,但是數據庫怎么辦呢?數據庫並不會自己自動更新,所以這時候就會有這樣的錯誤:
支持“StoreContext”上下文的模型已在數據庫創建后發生更改。請考慮使用 Code First 遷移更新數據庫
解決這樣的問題有兩種方案:重新創建數據庫和修改數據庫。
修改數據庫需要手動操作,重新創建數據庫可以通過某種方式讓它自動執行。一般我們在正式發布的時候,是不會修改我們的model,只有在測試的時候才會發生這種事情,所以,在開發的時候,采取第一種方法是最好的。
要想讓數據庫能夠自動創建,我們需要一個新的類:
public class UserIntializer : DropCreateDatabaseIfModelChanges<StoreContext> { protected override void Seed(StoreContext context) { base.Seed(context); } }
重新創建數據庫,會使得我們之前的數據全部消失,但如果我們想要在重新創建數據庫的時候,在某張表中保留原先的數值,而不是重新手動輸入,可以在Seed中這樣寫:
var Users = new List<Users> { new User{ UserID = 123, Name = "習駿", }; Users.ForEach(u => context.Users.Add(u));
創建完該類后,我們接下來要做的就是在我們的應用程序開始運行的時候能夠自動重建數據庫。要想實現該功能,我們必須到工程根目錄下的Global.ascx文件中進行配置。
Global.ascx文件中定義了當前工程所使用到的Application主類,它包含了一個Application_Start()事件處理器,在我們的應用程序第一次運行的時候就會觸發它里面的事件。
我們必須在該文件中添加以下的代碼:
System.Data.Entity.Database.SetInitializer<StoreContext>(new UserIntializer());
這里必須指定Database的命名空間全稱,就算我們正確的導入了它的命名空間也依然起不了作用,因為該方法是靜態方法。