本演練介紹瞭如何使用新資料庫進行 Code First 開發。我們用類定義一個模型,然後使用該模型創建一個資料庫,然後存儲和檢索數據。資料庫創建之後,我們使用 Code First 遷移將架構更改為我們發展後的模型。此外還介紹瞭如何使用數據註釋和 Fluent API 來配置模型。 ...
必備條件
要完成本演練,需要安裝 Visual Studio 2010 或 Visual Studio 2012。
如果使用的是 Visual Studio 2010,還需要安裝 NuGet。
1.創建應用程式
簡單起見,我們將構建一個使用 Code First 執行數據訪問的基本控制台應用程式。
- 打開 Visual Studio
- “文件”->“新建”->“項目…”
- 從左側菜單中選擇“Windows”和“控制台應用程式”
- 輸入 CodeFirstNewDatabaseSample 作為名稱
- 選擇“確定”
2.創建模型
我們使用類來定義一個非常簡單的模型。在 Program.cs 文件中進行定義,但是實際應用程式中,可能會將類分為若幹個單獨的文件,可能作為單獨的項目。
在 Program.cs 中的程式類定義下,添加以下兩個類。
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public 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.Posts 和 Post.Blog)。這將啟用實體框架的延遲載入功能。延遲載入意味著,嘗試訪問這些屬性的內容時,將自動從資料庫載入。
3.創建上下文
現在,可以定義派生上下文,用於表示資料庫的一個會話,以便我們查詢和保存數據。我們定義一個派生自 System.Data.Entity.DbContext 的上下文,併為模型中的每個類公開一個類型化 DbSet<TEntity>。
現在,開始使用來自實體框架的類型。因此,我們需要添加 EntityFramework NuGet 程式包。
- “項目”–>“管理 NuGet 程式包…”
註意:如果沒有“管理 NuGet 程式包…”選項,則應安裝 最新版本的 NuGet - 選擇“聯機”選項卡
- 選擇“EntityFramework”程式包
- 單擊“安裝”
在 Program.cs 頂部,為 System.Data.Entity 添加一個 using 語句。
using System.Data.Entity;
在 Program.cs 中的 Post 類下,添加以下派生上下文。
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
下麵是 Program.cs 現在應包含內容的完整列表。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
namespace CodeFirstNewDatabaseSample
{
class Program
{
static void Main(string[] args)
{
}
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public 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; }
}
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
}
這是我們開始存儲和檢索數據所需的全部代碼。顯然,後臺發生了許多事情。稍後,我們將進行瞭解。但是,首先讓我們看看它是如何運行的。
4.讀寫數據
實現 program.cs 中的 Main 方法,如下所示。這些代碼為上下文創建一個新實例,然後使用該實例插入新博客。之後,它使用 LINQ 查詢檢索資料庫中的所有博客(按標題的字母順序進行排序)。
class Program
{
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();
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...");
Console.ReadKey();
}
}
}
現在,可以運行應用程式,對其進行測試。
Enter a name for a new Blog: ADO.NET 博客 All blogs in the database: ADO.NET 博客 Press any key to exit... |
我的數據在哪裡?
按照約定,DbContext 已經創建了一個資料庫。
- 如果本地 SQL Express 實例可用(預設情況下隨 Visual Studio 2010 安裝),則 Code First 已對該實例創建了資料庫
- 如果 SQL Express 不可用,則 Code First 將嘗試使用 LocalDb(預設情況下隨 Visual Studio 2012 安裝)
- 資料庫以派生上下文的完全限定名命名,在我們的示例中,名稱為 CodeFirstNewDatabaseSample.BloggingContext
這些僅僅是預設約定,除此之外,還有多種方式可更改 Code First 所用的資料庫。有關更多信息,請參見DbContext 如何發現模型和資料庫連接 主題。
可以在 Visual Studio 中使用伺服器資源管理器連接至此資料庫
- “視圖”->“伺服器資源管理器”
- 右鍵單擊“數據連接”並選擇“添加連接…”
- 如果尚未從伺服器資源管理器連接至資料庫,則需要選擇 Microsoft SQL Server 作為數據源
- 連接至 LocalDb ((localdb)\v11.0) 或 SQL Express (.\SQLEXPRESS),具體取決於安裝情況
現在,可以檢查 Code First 已經創建的架構。
DbContext 通過查看我們定義的 DbSet 屬性,瞭解模型包含哪些類。隨後,它使用 Code First 約定的預設集來確定表和列的名稱,確定數據類型,查找主鍵等。本演練稍後將介紹如何重寫這些約定。
5.處理模型更改
現在更改模型,當我們進行更改時,還需要更新資料庫架構。為此,我們使用一個稱為“Code First 遷移”(或簡稱“遷移”)的功能。
“遷移”是一組有序的步驟,描述如何升級(和降級)資料庫架構。這些步驟(稱為“遷移”)中的每個步驟均包含一些代碼,用於描述要應用的更改。
第一步是為 BloggingContext 啟用 Code First 遷移。
- “工具”->“庫程式包管理器”->“程式包管理器控制台”
- 在程式包管理器控制臺中運行 Enable-Migrations 命令
- 一個新的 Migrations 文件夾已添加至項目中,它包含兩個文件:
- Configuration.cs — 此文件包含“遷移”將用來遷移 BloggingContext 的設置。在本演練中不需要進行任何更改,但是,在此處可以指定種子數據、為其他資料庫註冊提供程式、更改生成遷移的命名空間等。
- <時間戳>_InitialCreate.cs — 這是第一個遷移,它表示已經應用於資料庫的更改。應用更改的目的是將其從空資料庫遷移至包含博客和文章表的資料庫。儘管我們讓 Code First 自動創建這些表,現在我們選擇“遷移”(已轉化為一次“遷移”)。Code First 還在本地資料庫中記錄:該“遷移”已經應用。文件名中的時間戳用於排序。
現在,更改模型,向 Blog 類添加一個 Url 屬性:
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public virtual List<Post> Posts { get; set; }
}
- 在程式包管理器控制臺中運行 Add-Migration AddUrl 命令。
Add-Migration 命令檢查自上次遷移後是否有更改,並使用所有更改搭建新遷移。我們可以為遷移指定名稱;在本例中,將此遷移稱為“AddUrl”。
搭建的代碼表明:我們需要向 dbo.Blogs 表添加可容納字元串數據的 Url 列。如果需要,可以對搭建的代碼進行編輯,但是,在本例中,沒有這個必要。
namespace CodeFirstNewDatabaseSample.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class AddUrl : DbMigration
{
public override void Up()
{
AddColumn("dbo.Blogs", "Url", c => c.String());
}
public override void Down()
{
DropColumn("dbo.Blogs", "Url");
}
}
}
- 在程式包管理器控制臺中運行 Update-Database 命令。此命令將所有掛起的遷移應用於資料庫。InitialCreate 遷移已經應用,因此,這些遷移將僅應用新的 AddUrl 遷移。
提示:在調用 Update-Database 命令查看對資料庫執行的 SQL 時,可以使用 –Verbose 開關。
新的 Url 列已添加至資料庫中的 Blogs 表:
6.數據註釋
到目前為止,EF 發現了使用其預設約定的模型。但是,有時類不遵從約定,我們需要能夠執行進一步配置。對此有兩種方法;本節將介紹數據註釋,下一節將介紹 Fluent API。
- 向模型添加用戶類
public class User
{
public string Username { get; set; }
public string DisplayName { get; set; }
}
- 我們還需要向派生上下文添加一個集
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
}
- 如果嘗試添加遷移,會收到錯誤消息“EntityType‘User’未定義鍵。請為該 EntityType 定義鍵。”這是因為 EF 無法知道 Username 應為用戶的主鍵。
- 我們將使用數據註釋,因此需要在 Program.cs 的頂部添加一個 using 語句
using System.ComponentModel.DataAnnotations;
- 現在,註釋 Username 屬性,將它標識為主鍵
public class User
{
[Key]
public string Username { get; set; }
public string DisplayName { get; set; }
}
- 使用 Add-Migration AddUser 命令搭建一個遷移,將這些更改應用於資料庫
- 運行 Update-Database 命令,將新遷移應用於資料庫
現在,新表已添加至資料庫:
EF 支持的完整註釋列表為:
- KeyAttribute
- StringLengthAttribute
- MaxLengthAttribute
- ConcurrencyCheckAttribute
- RequiredAttribute
- TimestampAttribute
- ComplexTypeAttribute
- ColumnAttribute
- TableAttribute
- InversePropertyAttribute
- ForeignKeyAttribute
- DatabaseGeneratedAttribute
- NotMappedAttribute
7.Fluent API
上一節介紹瞭如何使用數據註釋來補充或重寫按約定檢測的內容。另一種模型配置方法是通過 Code First Fluent API。
大多數模型配置都可使用簡單數據註釋進行。Fluent API 是一種更高級的方法,除某些數據註釋不可能支持的更高級配置外,可以指定包含數據註釋所有功能的模型配置。數據註釋和 Fluent API 可一起使用。
要訪問 Fluent API,需要在 DbContext 中重寫 OnModelCreating 方法。假設我們需要重命名 User.DisplayName 存儲至 display_name 的列。
- 使用以下代碼重寫 BloggingContext 的 OnModelCreating 方法
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.Property(u => u.DisplayName)
.HasColumnName("display_name");
}
}
- 使用 Add-Migration ChangeDisplayName 命令搭建遷移,將這些更改應用於資料庫。
- 運行 Update-Database 命令,將新遷移應用於資料庫。
DisplayName 列現在重命名為 display_name:
摘要
本演練介紹瞭如何使用新資料庫進行 Code First 開發。我們用類定義一個模型,然後使用該模型創建一個資料庫,然後存儲和檢索數據。資料庫創建之後,我們使用 Code First 遷移將架構更改為我們發展後的模型。此外還介紹瞭如何使用數據註釋和 Fluent API 來配置模型。