EntityFramework 7 開發紀錄


博文目錄:

  • 暫時開發模式
  • 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)。

然后需要在 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(遷移)的部分用法,其實很簡單,總共就四步:

  1. Install-Package EntityFramework.SqlServer –Pre
  2. Install-Package EntityFramework.Commands -Pre
  3. Add-Migration MyFirstMigration
  4. Apply-Migration

EF7DbContext 並不需要任何配置,但試過之后會發現,一大堆的問題,而且解決方案也搜不到,已經困擾一兩天的時間了,下面紀錄下過程。

之前寫過一篇 EF Code First 的博文,里面有提到 EF 代碼遷移的使用方法(非 EF7 版本),大致為:

  1. Enable-Migrations
  2. Add-Migration Update-NewType-Name
  3. Update-Database

EF 7 代碼遷移命令的完整說明(來自 get-help {命令名稱} -full):

  1. Use-DbContext [-Context] <string> [[-Project] <string>] [<CommonParameters>]
  2. Add-Migration [-Name] <string> [[-Context] <string>] [[-Project] <string>] [<CommonParameters>]
  3. Apply-Migration [[-Migration] <string>] [[-Context] <string>] [[-Project] <string>] [<CommonParameters>]
  4. Update-Database [[-Migration] <string>] [[-Context] <string>] [[-Project] <string>] [<CommonParameters>]
  5. 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 中手動配置一下:

  1. Import-Module C:\Users\yuezhongxin\.kpm\packages\EntityFramework.Commands\7.0.0-beta1\tools\EntityFramework.psd1
  2. 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 是可以使用的:

其實問題出現的原因無非就是兩點:

  1. EntityFramework.Commands 中的 Migration 命令
  2. 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 的操作步驟:

  1. 命令行運行(安裝 KVM):@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/aspnet/Home/master/kvminstall.ps1'))"
  2. 退出命令行,再次打開,輸入命令:KVM upgrade
  3. cd 轉到 EF7 項目下(project.json 所在目錄),如:cd C:\Users\yuezhongxin\Desktop\EF7\src\EF7
  4. 增加遷移命令:k ef migration add initial
  5. 應用遷移命令: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

珍貴的參考資料:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM