zoukankan      html  css  js  c++  java
  • EntityFramework 7 开发纪录

    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] [[-Project] ] []
    2. Add-Migration [-Name] [[-Context] ] [[-Project] ] []
    3. Apply-Migration [[-Migration] ] [[-Context] ] [[-Project] ] []
    4. Update-Database [[-Migration] ] [[-Context] ] [[-Project] ] []
    5. 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:UsersyuezhongxinDesktopConsoleApp1packagesEntityFramework.6.1.1 oolsEntityFramework.psm1:713 char:28

    什么意思?就是因为“Path”参数问题,不能加载“Add-Migration”命令,和上面异常不同的是,这个异常给出错误地址了:“EntityFramework.6.1.1 oolsEntityFramework.psm1”,但有个问题是,我使用的是 EF7,为什么会报 EntityFramework.6.1.1 的异常,这个问题也困扰我很久,最后在一篇博文中找到答案及解决方式:Entity Framework 5.0系列之Code First数据库迁移,大致意思是说 Migration 命令没有加载最新版本的 EntityFramework,所以需要在 Package Manager Console 中手动配置一下:

    1. Import-Module C:Usersyuezhongxin.kpmpackagesEntityFramework.Commands7.0.0-beta1 oolsEntityFramework.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 的资料实在少得可怜,这个问题我也只探究到这一步,毕竟还要做事,就纪录到这,等待后续解决!

    珍贵的参考资料:

  • 相关阅读:
    git(1)-git关联GitHub-windows-转载
    jenkins(4)-jenkins配置邮件通知
    jenkins(3)-linux下安装jenkins(yum install方式)
    【PAT甲级】1090 Highest Price in Supply Chain (25 分)(DFS)
    【PAT甲级】1087 All Roads Lead to Rome (30 分)(MAP【int,string】,邻接表,DFS,模拟,SPFA)
    【PAT甲级】1018 Public Bike Management (30 分)(DFS,SPFA)
    Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)
    Atcoder Grand Contest 032C(欧拉回路,DFS判环)
    Educational Codeforces Round 62 (Rated for Div. 2)E(染色DP,构造,思维,组合数学)
    Atcoder Grand Contest 031C(构造,思维,异或,DFS)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4128239.html
Copyright © 2011-2022 走看看