Entity Framework (又稱ADO.NET Entity Framework) 是微軟以 ADO.NET 爲基礎所發展出來的對象關係對應 (O/R Mapping) 解決方案,早期被稱爲 ObjectSpace,現已經包含在 Visual Studio 2008 Service Pack 1 以及 .NET Framework 3.5 Service Pack 1 中發表。
ADO.NET Entity Framework 以 Entity Data Model (EDM) 爲主,將數據邏輯層切分爲三塊,分別爲 Conceptual Schema, Mapping Schema 與 Storage Schema 三層,其上還有 Entity Client,Object Context 以及 LINQ 可以使用。
下面說下我用 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 之間的關聯配置:
IT經典笑語錄:delphi就象吉普車,什麼路上都能開,卻什麼路上也開不好,pb就像是卡丁車,只能在固定線路上開,到了室外 就有些不穩了,vc就象是跑車,你開的起卻買不起,而且一旦發生故障,想修都找不到毛病在哪,java就像敞棚車,不管颳風下雨,還是豔陽高照,都能照開不誤,vb就是摩托車了,騎的時間越長,你越痛恨它!
-
OneToOne:一對一
-
OneToMany:一對多
- ManyToOne:多對一
EF7 Entity 之間的關聯配置更加簡單明瞭,EF 之前版本配置(HasRequired 或 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] [[-Project] ] []
-
Add-Migration [-Name] [[-Context] ] [[-Project] ] []
-
Apply-Migration [[-Migration] ] [[-Context] ] [[-Project] ] []
-
Update-Database [[-Migration] ] [[-Context] ] [[-Project] ] []
- Script-Migration [[-From] ] [[-To] ] [[-Context] ] [[-Project] ] [-Idempotent] []
首先,按照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 的資料實在少得可憐,這個問題我也只探究到這一步,畢竟還要做事,就紀錄到這,等待後續解決!
珍貴的參考資料:
-
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