Asp.net core中Migration工具使用的交流分享
a,ul>li,em{
color:deeppink !important;
}
h2>a{
text-decoration:none;
}
ul>li{
padding:3px;
}
ul{
width:512px;
}
li>p{
color:#333;
margin:0 !important;
}
hr{
border-color:deeppink;
}
em{
font-style:normal;
}
.passage{
text-indent:2em;
font-size:18px;
}
-->
一、文章参数
二、开篇碎语
三、主要内容
四、篇后总结
一、文章参数
- 开发工具:
visual studio 2015 community update 3 + .net core tools(preview2) + sqlserver2012 express
- 开发环境:
win10(版本14393)+ .net core(版本 1.0.0-preview2-003121)
- 项目名称:
AirMusic
- 项目模板:
Asp.net core WebApi(这里不用mvc模板,是因为mvc模板初始的内容太多,这里用不到)
- AirMusic源码地址:
二、开篇碎语
记得去年第一次做项目,用了asp.net mvc5,因此也第一接触了EntityFramework(版本是EF6)。 现在打算用asp.net core来完成一个项目,air music是学习asp.net core时新建的demo项目,以后学习core中遇到的一些问题一般会从这个项目产生,今天这篇文章是在migration初始化数据库时发生的一些问题。
三、主要内容
1、初始化的实体模型
public class Song
{
public int Id { get; set; }
[Required]
public string SongName { get; set; }
public virtual ICollection<ArtistSong> Artists { get; set; }
public virtual ICollection<SongListSong> SongLists { get; set; }
} //歌手
public class Artist
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Album> Albums { get; set; }
public virtual ICollection<ArtistSong> Songs { get; set; }
} //song with artist n:n table
public class ArtistSong
{
[Key]
public int ArtistId { get; set; }
[Key]
public int SongId { get; set; }
} //专辑
public class Album
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
public virtual ICollection<Song> Songs { get; set; }
} //歌单
public class SongList
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
public string Describe { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ICollection<SongListSong> Songs { get; set; }
} // song with songlist n:n table
public class SongListSong
{
[Key]
public int SongListId { get; set; }
[Key]
public int SongId { get; set; }
}
Store Models
2、引用EFcoore相关的Nuget包
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0"
(依赖了好多ef重要组件)
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
(引用了才可以试用migration)
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.0"
(我觉得是ef连接sqlserver的必须组件)
还有就是必须在project.json里的tools节点中添加"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",不然输入命令”Add Migration“时就会报出下面这句错误。
"No parameterless constructor………“这句错误是因为ApplicationDbContext(数据库上下文类)没有写下面这个构造函数报的错误。
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
3、配置数据库连接
Webapi模板已经创建好了appsetting.json文件,这个文件的作用和web.config是一样的

4、文章包袱:Migration过程中遇到的问题
在ApplicationDbContext重写的方法OnModelCreating
中,有一行代码
base.OnModelCreating(builder)
当我把这行代码注释掉时,迁移过程中就会报出如下错误:
很明显,错误发生的原因是IdentityUser没有被映射到ApplicationDbContext,所以可以知道这句代码的作用,就是用来映射Identity的几个实体类的,没有这句,数据库中就不会自动生成Users、Roles……等Table了,我还没有去github看这个方法的源码,但我觉得实际上就是第一次Add-Migration时,生成的源文件ApplicationDbContextModelSnapshot.cs 中的代码:
protected override void BuildModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.0.0-rtm-21431")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
{
b.Property<string>("Id"); b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken(); b.Property<string>("Name")
.HasAnnotation("MaxLength", ); b.Property<string>("NormalizedName")
.HasAnnotation("MaxLength", ); b.HasKey("Id"); b.HasIndex("NormalizedName")
.HasName("RoleNameIndex"); b.ToTable("AspNetRoles");
}); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd(); b.Property<string>("ClaimType"); b.Property<string>("ClaimValue"); b.Property<string>("RoleId")
.IsRequired(); b.HasKey("Id"); b.HasIndex("RoleId"); b.ToTable("AspNetRoleClaims");
}); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser", b =>
{
b.Property<string>("Id"); b.Property<int>("AccessFailedCount"); b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken(); b.Property<string>("Discriminator")
.IsRequired(); b.Property<string>("Email")
.HasAnnotation("MaxLength", ); b.Property<bool>("EmailConfirmed"); b.Property<bool>("LockoutEnabled"); b.Property<DateTimeOffset?>("LockoutEnd"); b.Property<string>("NormalizedEmail")
.HasAnnotation("MaxLength", ); b.Property<string>("NormalizedUserName")
.HasAnnotation("MaxLength", ); b.Property<string>("PasswordHash"); b.Property<string>("PhoneNumber"); b.Property<bool>("PhoneNumberConfirmed"); b.Property<string>("SecurityStamp"); b.Property<bool>("TwoFactorEnabled"); b.Property<string>("UserName")
.IsRequired()
.HasAnnotation("MaxLength", ); b.HasKey("Id"); b.HasIndex("NormalizedEmail")
.HasName("EmailIndex"); b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex"); b.ToTable("AspNetUsers"); b.HasDiscriminator<string>("Discriminator").HasValue("IdentityUser");
}); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd(); b.Property<string>("ClaimType"); b.Property<string>("ClaimValue"); b.Property<string>("UserId")
.IsRequired(); b.HasKey("Id"); b.HasIndex("UserId"); b.ToTable("AspNetUserClaims");
}); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider"); b.Property<string>("ProviderKey"); b.Property<string>("ProviderDisplayName"); b.Property<string>("UserId")
.IsRequired(); b.HasKey("LoginProvider", "ProviderKey"); b.HasIndex("UserId"); b.ToTable("AspNetUserLogins");
}); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId"); b.Property<string>("RoleId"); b.HasKey("UserId", "RoleId"); b.HasIndex("RoleId"); b.HasIndex("UserId"); b.ToTable("AspNetUserRoles");
}); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId"); b.Property<string>("LoginProvider"); b.Property<string>("Name"); b.Property<string>("Value"); b.HasKey("UserId", "LoginProvider", "Name"); b.ToTable("AspNetUserTokens");
}); modelBuilder.Entity("AirMusic.Models.ApplicationUser", b =>
{
b.HasBaseType("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
.WithMany("Claims")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
}); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser")
.WithMany("Claims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
}); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser")
.WithMany("Logins")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
}); modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
.WithMany("Users")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade); b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
}
一个让我很困惑的问题在进行第一次Migration时出现了。AirMusic的实体中,有这样一种关系:
但是神奇的事情发生了(我不想这样的):
migrationBuilder.CreateTable(
name: "ArtistSongs",
columns: table => new
{
ArtistId = table.Column<int>(nullable: false),
SongId = table.Column<int>(nullable: false),
//ArtistId1 = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ArtistSongs", x => new { x.ArtistId, x.SongId });
table.ForeignKey(
name: "FK_ArtistSongs_Artists_ArtistId",
column: x => x.ArtistId,
principalTable: "Artists",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
//table.ForeignKey(
// name: "FK_ArtistSongs_Artists_ArtistId1",
// column: x => x.ArtistId1,
// principalTable: "Artists",
// principalColumn: "Id",
// onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_ArtistSongs_Songs_SongId",
column: x => x.SongId,
principalTable: "Songs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}); migrationBuilder.CreateTable(
name: "SongListSongs",
columns: table => new
{
SongListId = table.Column<int>(nullable: false),
SongId = table.Column<int>(nullable: false),
//SongListId1 = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_SongListSongs", x => new { x.SongListId, x.SongId });
table.ForeignKey(
name: "FK_SongListSongs_Songs_SongId",
column: x => x.SongId,
principalTable: "Songs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_SongListSongs_SongLists_SongListId",
column: x => x.SongListId,
principalTable: "SongLists",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
//table.ForeignKey(
// name: "FK_SongListSongs_SongLists_SongListId1",
// column: x => x.SongListId1,
// principalTable: "SongLists",
// principalColumn: "Id",
// onDelete: ReferentialAction.Restrict);
});
初次Migration中发生意外的代码(注释的那些)
自动添加了带artist1和songlist1的字段,我很希望知道的朋友告诉我解决的办法!!我实在不知道怎么让EF不自动添加这个多余的字段,所以我把那些多余的字段都注释掉后,才update-database到数据库:
song-artist[N:N] , song-songlist[N:N]
在ApplicationDbContext的OnModelCreating方法里,可以手动的配置数据库中的关系,像什么组合主键啦,组合外键啦等等各种约束,都可以 实现。特别是数据库中实体的关系配置(1:1,1:N,N:N),例如:用方法builder.HasOne().WithMany()就可以建立[1:N]的关系。AirMusic初次Migration中,我也手动的配置了一些关系:
var entityAS=builder.Entity<ArtistSong>();
entityAS.HasKey("ArtistId", "SongId");
entityAS.HasOne<Artist>()
.WithMany()
.HasForeignKey("ArtistId"); var entitySS = builder.Entity<SongListSong>();
entitySS.HasKey("SongListId", "SongId");
entitySS.HasOne<SongList>()
.WithMany()
.HasForeignKey("SongListId");
上面代码的作用是,ArtistId和SongId设为ArtistSong的组合主键,ArtistSong的ArtistId设为Artist的外键。entitySS的作用也大致相同。
四、篇后总结
第一次完整的写一篇博文,晚上去吃饭是电脑自动重启更新了,vscode里的代码都没保存,打开博客园文章管理发现什么都没了,难过的就去听歌睡觉了。第二天起来打算从新来过时,发现有一行“自动保存恢复”,那个感觉就和中了100块的彩票一样。
希望有人看完这篇文章吧,新写手最需要的就是多给建议呀!谢谢
Asp.net core中Migration工具使用的交流分享的更多相关文章
- ASP.NET Core 中文文档 第二章 指南(4.6)Controller 方法与视图
原文:Controller methods and views 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘) .张仁建(第二年.夏) .许登洋(Seay) .姚阿勇 ...
- 如何在ASP.NET Core中实现一个基础的身份认证
注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ...
- 在ASP.NET Core中实现一个Token base的身份认证
注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and authorization in ASP.NET Core 在 ...
- 如何在ASP.NET Core中应用Entity Framework
注:本文提到的代码示例下载地址> How to using Entity Framework DB first in ASP.NET Core 如何在ASP.NET Core中应用Entity ...
- [转]如何在ASP.NET Core中实现一个基础的身份认证
本文转自:http://www.cnblogs.com/onecodeonescript/p/6015512.html 注:本文提到的代码示例下载地址> How to achieve a bas ...
- 在 ASP.NET Core 中集成 Skywalking APM
前言 大家好,今天给大家介绍一下如何在 ASP.NET Core 项目中集成 Skywalking,Skywalking 是 Apache 基金会下面的一个开源 APM 项目,有些同学可能会 APM ...
- ASP.NET Core中使用GraphQL - 第四章 GraphiQL
ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...
- ASP.NET Core中使用GraphQL - 第六章 使用EF Core作为持久化仓储
ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...
- 在Asp.Net Core中集成Kafka
在我们的业务中,我们通常需要在自己的业务子系统之间相互发送消息,一端去发送消息另一端去消费当前消息,这就涉及到使用消息队列MQ的一些内容,消息队列成熟的框架有多种,这里你可以读这篇文章来了解这些MQ的 ...
随机推荐
- 线段拟合(带拉格朗日乘子,HGL)
线段特征上的扫描点满足 (1).本文的线段特征定义为:L: [dL, φL, PLs, PLe]T,如图1所示.其中,dL为笛卡尔坐标系中原点(激光传感器所在位置)到线段的距离, φL为线段特征的倾角 ...
- 我和我的广告前端代码(四):后台系统中,初尝vue、vue-cli
有一段都在重构之前文章<我和我的广告前端代码(三):一次重来的机会,必要的技术选型>中提到的广告前台展示项目,原有的基于页面的请求,改成了单广告位请求在这个过程中经历了好几次架构变更以及项 ...
- Ajax,Json数据格式
同步和异步 同步现象:客户端发送请求到服务器端,当服务器返回响应之前,客户端都处于等待 卡死状态 异步现象:客户端发送请求到服务器端,无论服务器是否返回响应,客户端都可以随 意做其他事 ...
- 数据库——MySQL——权限管理
关于MySQL的权限管理,可以理解为是MySQL运行你做的事情.比如MySQL允许你执行select操作那么你就不能用update操作.如果你让你在某台机器上连接MySQL,那么你就不能在这个机器以外 ...
- JavaScript自己整理的基础-01
1.JavaScript 简介: JavaScript是互联网上最流行的脚本语言,所有现代的HTML都使用JavaScript.既然是脚本语言,那么它的特点就有一下三种: (1)弱类型: (2)解释型 ...
- 搭建基本的React Native开发环境
步骤如下: 1.安装HomeBrew,命令如下: 在终端输入命令:$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Home ...
- 监控tomcat工具使用
用LambdaProbe监控Tomcat 简介: Lambda Probe(以前称为Tomcat Probe)是一款实时监控和管理的Apache Tomcat实例的基本工具.Lambda Probe ...
- linux 查看系统当前时间,修改时间
linux 查看系统当前时间,修改时间1. 查看时间和日期命令 : "date"2.设置时间和日期例如:将系统日期设定成2018年6月8日的命令命令 : "date -s ...
- centos7-mongodb3.4.6集群的搭建
0.需要环境 安装包:mongodb-linux-x86_64-3.4.6.tgz 安装路径:/usr/mongodb 服务器: 192.168.177.131/132/133 mongos 2000 ...
- TCP回话劫持原理和利用
由于 TCP 协议并没有对 TCP 的传输包进行身份验证,所以在我们知道一个 TCP 连接中的 seq 和 ack 的信息后就可以很容易的伪造传输包,假装任意一方与另一方进行通信,我们将这一过程称为 ...