博文目錄:
- 暫時開發模式
- Code First 具體體現
- DbContext 配置
- Entity 映射關聯配置
- Migration 問題紀錄(已解決)
之前的一篇博文:EF7 Code First Only-所引發的一些“臆想”
寫這篇博文的緣由是:因為這次 EF7 更新比較大,很多東西都是全新模式,而且 EF7 相關的資料實在太少,所以只能通過 GitHub 上的 Entity Framework Wiki 進行參考學習,但資源有限,而且坑也不少,沒辦法,自己動手,豐衣足食。
下面說下我用 EF7 開發項目的一些筆記(待補充):
暫時開發模式
說明:The EF7 NuGet packages use some new metadata that is only supported in NuGet 2.8.3 or higher.
EF7 目前只能通過 NuGet 進行管理,所以,首先確定你的 Visual Studio 中的 NuGet 為最新版本(最低支持 2.8.3,最新版本 3.0)。
- Visual Studio 2015 - No updates needed, a compatible version of NuGet is included.
- Visual Studio 2013 - You can download a compatible version from Visual Studio Gallery. A compatible version is also included in VS 2013 Update 4.
- Visual Studio 2010 and 2012 - You can download a compatible version from Visual Studio Gallery.
然后需要在 Tools –> NuGet Package Manager –> Package Manager Settings 中配置 Package Sources:https://www.myget.org/F/aspnetvnext/api/v2/,VS 2015 不需要進行添加。
我使用的是 VS 2015 開發的,所以 NuGet 不需要任何配置,使用 EF 之前,需要添加一個類庫項目。

這是 VS 2015 中 ASP.NET 5 的三種模版,首先需要明確的是,ASP.NET 5 Class Library 項目可以在其他兩個項目之前進行引用,但不能被其他非 ASP.NET 5 項目引用,相反,ASP.NET 5 項目也不能引用其他類型的類庫項目,如果強行引用,就會抱下面錯誤:

所以說,如果你的 Web 項目為 ASP.NET 5,那你開發的所有類庫項目必須為 ASP.NET 5 Class Library 類型的。
Code First 具體體現
創建 ASP.NET 5 Class Library 類型的 EF7 項目,像平常 EF 開發一樣,我們需要在 EF7 項目中添加項,但你會發現,選擇項模版中並沒有“ADO.NET Entity Date Model”項。
EF6:
EF7:
“ADO.NET Entity Date Model”,就是“Code First Only”的具體表現,沒辦法,EF7 逼着你自行寫實體代碼。
DbContext 配置
EF7DbContext 示例代碼:
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Metadata;
using System;
namespace EF7
{
public class EF7DbContext : DbContext
{
public DbSet<Entity> Entities { get; set; }
protected override void OnConfiguring(DbContextOptions builder)
{
builder.UseSqlServer(@"data source=.;initial catalog=EF7Db;integrated security=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity>()
.ForRelational()
.Table("Entities");
modelBuilder.Entity<Entity>()
.Key(n => n.Id);
modelBuilder.Entity<Entity>()
.Property(t => t.Id)
.GenerateValuesOnAdd(false);
base.OnModelCreating(modelBuilder);
}
}
}
OnModelCreating 方法沒有變化,變化的是內部實現,映射配置后面講下,OnConfiguring 是新加入的,builder.UseSqlServer 的作用就是綁定連接字符串,相當於之前版本 App.config 中的 connectionStrings,這個配置也可以在 ASP.NET 5 Web 的 Startup.cs 中進行配置,如下:
public class Startup
{
public Startup(IHostingEnvironment env)
{
// Setup configuration sources.
Configuration = new Configuration()
.AddJsonFile("config.json")
.AddEnvironmentVariables();
}
public IConfiguration Configuration { get; set; }
// This method gets called by the runtime.
public void ConfigureServices(IServiceCollection services)
{
// Add EF services to the services container.
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<CNBlogsNewsDbContext>();
//.AddDbContext<CNBlogsNewsDbContext>(options =>
//{
// //options.UseSqlServer(Configuration.Get("Data:DefaultConnection:ConnectionString"));
// options.UseSqlServer();
//});
// Add MVC services to the services container.
services.AddMvc();
// Uncomment the following line to add Web API servcies which makes it easier to port Web API 2 controllers.
// You need to add Microsoft.AspNet.Mvc.WebApiCompatShim package to project.json
// services.AddWebApiConventions();
}
}
AddEntityFramework 的配置模式有很多,比如上面配置中就不使用 EF7DbContext 中的連接字符串,而是讀取 config.json 配置文件中的 ConnectionString,詳細內容在 ASP.NET 5 記錄中再進行說明,在 EF7DbContext 的示例代碼中,我們會發現沒有了 EF7DbContext 構造函數,之前都是在構造函數中寫一大堆東西,比如:
public EF6DbContext()
: base("name=EF6Db")
{
this.Configuration.LazyLoadingEnabled = false;
Database.SetInitializer<EF6DbContext>(null);
}
這部分配置都移到 EF7DbContext 中的 OnConfiguring(DbContextOptions) 進行配置。
更多內容,請參考:Configuring a DbContext
Entity 映射關聯配置
示例代碼:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity>()
.ForRelational()
.Table("Entities");
modelBuilder.Entity<Entity>()
.Key(n => n.Id);
modelBuilder.Entity<Entity>()
.Property(t => t.Id)
.GenerateValuesOnAdd(false);
modelBuilder.Entity<ChildEntity>()
.Key(n => n.Id);
modelBuilder.Entity<ChildEntity>()
.ManyToOne(n => n.Entity, t => t.ChildEntities)
.ForeignKey(t => t.EntityId);
base.OnModelCreating(modelBuilder);
}
對 Entity 屬性的一些配置,我們也可以在屬性的上面進行配置(比如 Key、Required、DataType 等),命令空間:System.ComponentModel.DataAnnotations,Table 配置是我無意間發現的,我原以為 EF7 不能對 Entity 進行表的重命名,之前我記得在 EF6 中是有 ToTable() 方法的,或者在 Entity 上面進行 Table() 屬性配置,但在 EF7 中改為了 ForRelational,所在程序集為:EntityFramework.Relational,GenerateValuesOnAdd 的配置說明是否為 identity,之前 EF 版本配置為:HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity),Entity 之間的關聯配置:
- OneToOne:一對一
- OneToMany:一對多
- ManyToOne:多對一
EF7 Entity 之間的關聯配置更加簡單明了,EF 之前版本配置(HasOptional 或 HasRequired):
HasOptional(x => x.ParentMessage)
.WithMany()
.Map(x => x.MapKey("ParentID"))
//.HasForeignKey(c => c.ParentID)
.WillCascadeOnDelete(false);
Migration 問題紀錄
參考:Using EF7 in Traditional .NET Applications
這是 EF7 的官方使用說明,其中有提到 Migration(遷移)的部分用法,其實很簡單,總共就四步:
Install-Package EntityFramework.SqlServer –Pre
Install-Package EntityFramework.Commands -Pre
Add-Migration MyFirstMigration
Apply-Migration
EF7DbContext 並不需要任何配置,但試過之后會發現,一大堆的問題,而且解決方案也搜不到,已經困擾一兩天的時間了,下面紀錄下過程。
之前寫過一篇 EF Code First 的博文,里面有提到 EF 代碼遷移的使用方法(非 EF7 版本),大致為:
Enable-Migrations
Add-Migration Update-NewType-Name
Update-Database
EF 7 代碼遷移命令的完整說明(來自 get-help {命令名稱} -full):
Use-DbContext [-Context] <string> [[-Project] <string>] [<CommonParameters>]
Add-Migration [-Name] <string> [[-Context] <string>] [[-Project] <string>] [<CommonParameters>]
Apply-Migration [[-Migration] <string>] [[-Context] <string>] [[-Project] <string>] [<CommonParameters>]
Update-Database [[-Migration] <string>] [[-Context] <string>] [[-Project] <string>] [<CommonParameters>]
Script-Migration [[-From] <string>] [[-To] <string>] [[-Context] <string>] [[-Project] <string>] [-Idempotent] [<CommonParameters>]
首先,按照EF7 Wiki 說明,在 Package Manager Console 中輸入:Add-Migration MyFirstMigration 命令,會報如下錯誤:

異常完整信息:Add-Migration : The term 'Add-Migration' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was in.
什么意思呢?直接說就是找不到“Add-Migration”命令,EF7 Migration 的所有命令管理都在 EntityFramework.Commands 程序集,所以我們使用 Migration 之前,都必須 NuGet 安裝一下,找不到“Add-Migration”命令,這個問題困擾我很久,也沒有找到相關資料,因為 Migration 的命令方式都是 PowerShell,我對這東西一竅不通,沒辦法,后來我嘗試不使用 EF7,而是使用 EF6 進行 Migration 配置,發現是可以的,這就很奇怪,回過頭再用 EF7 輸入命令“Add-Migration”,就會報另一種錯誤:

異常完整信息:Join-Path : Cannot bind argument to parameter 'Path' because it is null.At C:\Users\yuezhongxin\Desktop\ConsoleApp1\packages\EntityFramework.6.1.1\tools\EntityFramework.psm1:713 char:28
什么意思?就是因為“Path”參數問題,不能加載“Add-Migration”命令,和上面異常不同的是,這個異常給出錯誤地址了:“EntityFramework.6.1.1\tools\EntityFramework.psm1”,但有個問題是,我使用的是 EF7,為什么會報 EntityFramework.6.1.1 的異常,這個問題也困擾我很久,最后在一篇博文中找到答案及解決方式:Entity Framework 5.0系列之Code First數據庫遷移,大致意思是說 Migration 命令沒有加載最新版本的 EntityFramework,所以需要在 Package Manager Console 中手動配置一下:
Import-Module C:\Users\yuezhongxin\.kpm\packages\EntityFramework.Commands\7.0.0-beta1\tools\EntityFramework.psd1
Install-Package EntityFramework.Commands -IncludePrerelease
在 EF 之前版本中 EntityFramework.psd1 文件位置都會在 EntityFramework 程序集文件中,但在 EF7 中,被分離在了 EntityFramework.Commands 程序集文件中了,第二步的作用是重新加載程序集。

異常完整信息:The names of some imported commands from the module 'EntityFramework' include unapproved verbs that might make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of approved verbs, type Get-Verb.
Import-Module EF6 是成功的,但 Import-Module EF7 就會出現上面的警告信息,具體原因不得而知,在 Package Manager Console 中輸入“Add-Migration MyFirstMigration”命令,會出現下面異常:

異常完整信息:Add-Migration : Cannot bind argument to parameter 'Path' because it is null.At line:1 char:1
但輸入“get-help Add-Migration -full”命令(查看 Add-Migration 幫助信息),就會發現 Add-Migration 命令並沒有任何問題,也就是說 EntityFramework.Commands 是可以使用的:

其實問題出現的原因無非就是兩點:
- EntityFramework.Commands 中的 Migration 命令
- EF7DbContext 配置
網上關於 EF7 Migration 的資料實在少得可憐,這個問題我也只探究到這一步,畢竟還要做事,就紀錄到這,等待后續解決!
》》》》》》》》》》》》》》》》》》》》》華麗分割線,EF7 Migration 問題解決《《《《《《《《《《《《《《《《《《《《《
原本已經放棄 EF7 Migration,這篇博文也只是做一個問題記錄,但博文發布出來有一位園友 codepat,在評論中附帶了一個 EF7 Migration 參考地址:http://www.asp.net/vnext/overview/aspnet-vnext/vc,主要是說明 EF7 Migration 的操作通過 KVM 完成,我上面所有的嘗試都是通過 Package Manager Console 命令完成的,后來 EF wiki 上也更新了一篇 KVM 命令的博文:Migrations commands (high-level experience),但文中只是簡單說了幾個命令,並沒有詳細講述,“Migrations commands (high-level experience)”,這個命名不知道是不是說明原來 Package Manager Console 命令已經不能使用,也就是上面一直出現的報錯問題,還是 EF7 Migration 只能通過 KVM 命令進行操作,下面紀錄下使用 KVM 的操作步驟:
- 命令行運行(安裝 KVM):
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/aspnet/Home/master/kvminstall.ps1'))"
- 退出命令行,再次打開,輸入命令:
KVM upgrade
- cd 轉到 EF7 項目下(project.json 所在目錄),如:
cd C:\Users\yuezhongxin\Desktop\EF7\src\EF7
- 增加遷移命令:
k ef migration add initial
- 應用遷移命令:
k ef migration apply
project.json 示例代碼:
{
"version": "1.0.0-*",
"dependencies": {
"EntityFramework.SqlServer": "7.0.0-beta1",
"EntityFramework.Commands": "7.0.0-beta1",
"EntityFramework": "7.0.0-beta1",
"EntityFramework.Migrations": "7.0.0-beta1",
"EntityFramework.Relational": "7.0.0-beta1"
},
"commands": {
"ef": "EntityFramework.Commands"
},
"frameworks" : {
"aspnet50" : {
"dependencies": {
}
},
"aspnetcore50" : {
"dependencies": {
"System.Runtime": "4.0.20-beta-22231"
}
}
}
}
運行操作圖:

困擾幾天的問題終於解決了,這種感覺比中 500W 的彩票還要好,再次感謝園友 codepat。
珍貴的參考資料:
- Getting Started with EF7 Nightly Builds
- What is EF7 all about
- MusicStore
- Using EF7 in Traditional .NET Applications
- Configuring a DbContext
- Getting started with ASP.NET 5 MVC 6 Web API & Entity Framework 7
- Migrations commands (high-level experience)
- Code First Migrations
- Entity Framework 5.0系列之Code First數據庫遷移
- EF7 NuGet Commands
- EF Migrations Command Reference
- Using EF7 in Windows Phone & Store Applications