EntityFramework 7 开发纪录

本文记录了使用EF7进行开发的一些心得体验,包括暂时开发模式、CodeFirst的具体体现、DbContext配置、Entity映射关联配置等内容,并详细记录了解决EF7 Migration过程中遇到的问题。

博文目录:

  • 暂时开发模式
  • 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 之前,需要添加一个类库项目。

271413451848721.png

这是 VS 2015 中 ASP.NET 5 的三种模版,首先需要明确的是,ASP.NET 5 Class Library 项目可以在其他两个项目之前进行引用,但不能被其他非 ASP.NET 5 项目引用,相反,ASP.NET 5 项目也不能引用其他类型的类库项目,如果强行引用,就会抱下面错误:

271419341843634.png

所以说,如果你的 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:
271425169812108.png

EF7:
271425551066293.png

“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 命令,会报如下错误:

271554346992395.png

异常完整信息: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”,就会报另一种错误:

271738410438733.png

异常完整信息: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 程序集文件中了,第二步的作用是重新加载程序集。

271814558097031.png

异常完整信息: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”命令,会出现下面异常:

271818532319397.png

异常完整信息: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 是可以使用的:

271823165126330.png

其实问题出现的原因无非就是两点:

  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"
            }
        }
    }
}

运行操作图:

281509235596509.png

困扰几天的问题终于解决了,这种感觉比中 500W 的彩票还要好,再次感谢园友 codepat

珍贵的参考资料:


本文转自田园里的蟋蟀博客园博客,原文链接:http://www.cnblogs.com/xishuai/p/ef7-develop-note.html,如需转载请自行联系原作者
仓库管理系统——入库功能(用idea完成) 2.1.业务需求 你的开发团队现在正在开发仓库管理系统,其中你负责的功能是原材料入库登记,入库时,需要登记一下入库的原材料放置在哪个仓库(仓位号)和哪个货位(货位号)上,以及入库的数量是多少。登记完毕后,将该原材料的库存数量增加相应数量。 2.2.业务分析 原材料入库主要是要登记原材料入库的位置,企业有多个仓库,每个仓库里也会有多个货位,你要登记你入库的这一批原材料放在仓库哪个位置上了。由于仓库里原材料已经有库存了,那么当你入库登记成功后,需要将该类原材料的库存数量也相应的增加。 2.3.事务分析 入库登记和库存数量增加这两步业务具备事务性,要么成功就一起成功,要么失败就一起失败。 2.4.创建Java web项目 4、使用maven archetype新建一个javaweb项目,项目名:warehouse 该项目的maven坐标向量如下: Groupid:cn.edu.sdcet Artifacedid:warehouse Version:1.0-SNAPSHOT 5、在src/main/java目录下,新建软件包(package)cn.edu.sdcet 6、创建软件分层: 在该软件包下,分别新建分层软件包(package):controller/serivce/service.impl/dao/entity 2.5.集成SSM开发框架进项目 4、在pom.xml中配置,使用maven将SSM框架所需的jar包引入项目 5、在resource目录下,新建spring.xml和springmvc.xml,将spring框架和springmvc框架加载时所需的配置文件做好定义 6、在web.xml中配置,将spring和springmvc框架引入java web项目 2.6.分析并创建数据库结构 在mysql中,新建数据库warehouse,新建数据表Indocument(入库单表)、Inventory(库存数量表)。 Indocument表(入库单表)包含以下字段: 文本类型的docId(入库单编号)——主键 文本类型的materialid(原材料id) 时间类型的date(入库时间:年月日时分秒) 文本类型的operator(办理该入库业务的经办人姓名) 数值类型的warehouseNo(仓位号) 数值类型的locationNo(货位号) 数值类型的inNum(入库数量) Inventory(库存数量表)包含以下字段: 文本类型的materialid(原材料id)——主键 数值类型的haveNum(库存数量) 注意:要求使用sql语句完成上述建库建表。 2.7.定义实体类 在cn.edu.sdcet.entity软件包下,新建2个JavaBean实体类。分别是Indocument(入库单)、Inventory(库存数量),类属性对应数据表的相应字段。 注意:JavaBean的定义规则。 2.8.开发数据持久层 3、基于Mybatis的Mapper映射方式,新建Mapper映射文件和接口类。 4、为Indocument表建立新增单据的方法addDocument,执行后在相应数据表中插入一条新纪录。 5、为Inventory表建立增加库存方法addHaveNum,执行后在相应数据表中查询是否存在该原材料的库存,如果存在,则修改该原材料的库存数量,如果不存在,则新增一条库存数量的数据。 2.9.开发控制层和业务逻辑层Bean 要求:在Controller、Service和Dao层,采用自动装配的方式声明和注入bean类。 7、创建Service层的2个接口类,接口名IndocumentService和InventoryService。 8、分别创建2个接口类的实现类IndocumentServiceImpl和InventoryServiceImpl。 9、在IndocumentService接口中,声明addDocument方法,实现类中对该方法予以业务逻辑的实现。通过调用数据持久层对应方法,完成新增入库单据(含修改库存数量)的功能,分析判断addDocument方法是否需要事务管理。如果需要,则声明事务管理注解。 10、在InventoryService接口中,声明addHaveNum方法,实现类中对该方法予以业务逻辑的实现。通过调用数据持久层对应方法,完成在修改库存数量的功能,分析判断addHaveNum方法是否需要事务管理。如果需要,则声明事务管理注解。 11、创建Controller层的bean类,类名IndocumentController,提供入库方法Indocument(),接收浏览器发送的入库单号、原材料id、入库时间、经办人姓名、入库存放的仓位号、入库存放的货位号、入库数量。
最新发布
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值