• 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 的资料实在少得可怜,这个问题我也只探究到这一步,毕竟还要做事,就纪录到这,等待后续解决!

    珍贵的参考资料:

  • 相关阅读:
    C#飞行棋总结
    用python+pygame写贪吃蛇小游戏
    光线步进——RayMarching入门
    EasyX库进行图片绘制函数
    Unity复杂的旋转-欧拉角和四元数
    MATLAB GUI制作快速入门
    Three.js模型隐藏或显示
    Qt 为QPushButton、QLabel添加鼠标移入移出事件
    Unity c# 状态机的简单入门
    JavaFX Chart设置数值显示
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4128239.html
Copyright © 2020-2023  润新知