用户 table 不是使用 Entity Framework Core 3.1 在 MySql 数据库中创建的(代码优先方法)
The User table is not created in MySql database using Entity Framework Core 3.1 (Code-first approach )
如何使用 Code First 方法和 Entity Framework Core 3.1 在 MySql 数据库中创建用户 table?
"DataAccessMySqlProvider": "server=localhost;database=jahan_alpha;uid=xxxx;password=xxxx" in appsettings.json
并且在 startup.cs 中:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySQL(Configuration["ConnectionStrings:DataAccessMySqlProvider"],
b => b.MigrationsAssembly("Alpha.DataAccess")));
// .UseMySQL is in Microsoft.EntityFrameworkCore namespace
}
I 运行 Add-Migration Init-MySql-database
然后 Update-database
在程序包管理器控制台中。
这样做之后,我得到了这个错误:
PM> Update-Database Build started... Build succeeded.
Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 3.1.3 initialized 'ApplicationDbContext' using provider 'Pomelo.EntityFrameworkCore.MySql' with options:
MigrationsAssembly=Alpha.DataAccess
Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1,299ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE DATABASE `jahan_alpha`; Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (9,281ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE `__EFMigrationsHistory` (
`MigrationId` varchar(95) NOT NULL,
`ProductVersion` varchar(32) NOT NULL,
CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`)
); Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (118ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='jahan_alpha' AND TABLE_NAME='__EFMigrationsHistory';
Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT `MigrationId`, `ProductVersion`
FROM `__EFMigrationsHistory`
ORDER BY `MigrationId`; Microsoft.EntityFrameworkCore.Migrations[20402]
Applying migration '20200515231101_Init-MySql'. Applying migration '20200515231101_Init-MySql'. fail:
Microsoft.EntityFrameworkCore.Database.Command[20102]
Failed executing DbCommand (181ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE `User` DROP INDEX `UserNameIndex`; Failed executing DbCommand (181ms) [Parameters=[], CommandType='Text',
CommandTimeout='30'] ALTER TABLE `User` DROP INDEX `UserNameIndex`;
MySql.Data.MySqlClient.MySqlException (0x80004005): Table
'jahan_alpha.user' doesn't exist --->
MySql.Data.MySqlClient.MySqlException (0x80004005): Table
'jahan_alpha.user' doesn't exist
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ResultSet.cs:line 49
at MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 130
at MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 391
at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\Core\CommandExecutor.cs:line 62
at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlCommand.cs:line 226
at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlCommand.cs:line 74
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Pomelo.EntityFrameworkCore.MySql.Migrations.Internal.MySqlMigrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Table 'jahan_alpha.user' doesn't exist
ApplicationDbContext:
namespace Alpha.DataAccess
{
public class ApplicationDbContext : IdentityDbContext<User, Role, int, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
// some codes...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// it should be placed here, otherwise it will rewrite the following settings!
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<RoleClaim>(builder =>
{
builder.HasOne(roleClaim => roleClaim.Role).WithMany(role => role.Claims).HasForeignKey(roleClaim => roleClaim.RoleId);
builder.ToTable("RoleClaim");
});
modelBuilder.Entity<Role>(builder =>
{
builder.ToTable("Role");
});
modelBuilder.Entity<UserClaim>(builder =>
{
builder.HasOne(userClaim => userClaim.User).WithMany(user => user.Claims).HasForeignKey(userClaim => userClaim.UserId);
builder.ToTable("UserClaim");
});
modelBuilder.Entity<UserLogin>(builder =>
{
builder.HasOne(userLogin => userLogin.User).WithMany(user => user.Logins).HasForeignKey(userLogin => userLogin.UserId);
builder.ToTable("UserLogin");
});
modelBuilder.Entity<User>(builder =>
{
builder.ToTable("User"); //.HasMany(e => e.Comments).WithOne().OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<UserRole>(builder =>
{
builder.HasOne(userRole => userRole.Role).WithMany(role => role.Users).HasForeignKey(userRole => userRole.RoleId);
builder.HasOne(userRole => userRole.User).WithMany(user => user.Roles).HasForeignKey(userRole => userRole.UserId);
builder.ToTable("UserRole");
});
modelBuilder.Entity<UserToken>(builder =>
{
builder.HasOne(userToken => userToken.User).WithMany(user => user.UserTokens).HasForeignKey(userToken => userToken.UserId);
builder.ToTable("UserToken");
});
// some codes...
}
public static async Task CreateAdminAccount(IServiceProvider serviceProvider, IConfiguration configuration)
{
UserManager<User> userManager = serviceProvider.GetRequiredService<UserManager<User>>();
RoleManager<Role> roleManager = serviceProvider.GetRequiredService<RoleManager<Role>>();
string userName = configuration["Data:AdminUser:Name"];
string email = configuration["Data:AdminUser:Email"];
string password = configuration["Data:AdminUser:Password"];
string role = configuration["Data:AdminUser:Role"];
if (await userManager.FindByNameAsync(userName) == null)
{
if (await roleManager.FindByNameAsync(role) == null)
{
await roleManager.CreateAsync(new Role(role));
}
User user = new User
{
Email = email,
UserName = userName
};
var result = userManager.CreateAsync(user, password);
if (result.IsCompletedSuccessfully)
{
await userManager.AddToRoleAsync(user, role);
}
}
}
}
}
基于执行的第一个命令是 ALTER DATABASE
这一事实,我假设 1) 当您生成初始命令时,您已经有一个带有 table User
的手动生成的数据库迁移和 2) 然后你删除了数据库 3) 然后你 运行 Update-Database
命令。
将迁移视为将数据库从一个 table 状态移动到另一个状态的增量补丁。如果你想在更新数据库时看到实际的 SQL 会是 运行,你可以发出 dotnet ef migrations script -i -o migrations.sql
命令。这将生成一个完整的脚本,其中包含从初始状态到当前状态的所有迁移。
我进一步假设您在隐藏的 // some codes...
代码块 // some codes...
某处的 ApplicationDbContext
中实际上有一个 DbSet<User>
属性
正如评论中已经指出的那样,您需要做的是;
- 从服务器
localhost
删除 jahan_alpha
数据库
- 从您的项目中完全删除
Migrations
文件夹
- 运行
dotnet ef migrations add initial
- 运行
dotnet ef migrations script -i -o migrations.sql
- 验证
migrations.sql
文件中的 SQL 命令是否正确(例如 CREATE DATABASE
在 ALTER DATABASE
的任何实例之前)
- 现在 运行
dotnet ef database update
- 这将生成 jahan_alpha
数据库,其中包含代码优先项目中定义的模式
如何使用 Code First 方法和 Entity Framework Core 3.1 在 MySql 数据库中创建用户 table?
"DataAccessMySqlProvider": "server=localhost;database=jahan_alpha;uid=xxxx;password=xxxx" in appsettings.json
并且在 startup.cs 中:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySQL(Configuration["ConnectionStrings:DataAccessMySqlProvider"],
b => b.MigrationsAssembly("Alpha.DataAccess")));
// .UseMySQL is in Microsoft.EntityFrameworkCore namespace
}
I 运行 Add-Migration Init-MySql-database
然后 Update-database
在程序包管理器控制台中。
这样做之后,我得到了这个错误:
PM> Update-Database Build started... Build succeeded.
Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 3.1.3 initialized 'ApplicationDbContext' using provider 'Pomelo.EntityFrameworkCore.MySql' with options:
MigrationsAssembly=Alpha.DataAccess
Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1,299ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE DATABASE `jahan_alpha`; Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (9,281ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE `__EFMigrationsHistory` (
`MigrationId` varchar(95) NOT NULL,
`ProductVersion` varchar(32) NOT NULL,
CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`)
); Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (118ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='jahan_alpha' AND TABLE_NAME='__EFMigrationsHistory';
Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT `MigrationId`, `ProductVersion`
FROM `__EFMigrationsHistory`
ORDER BY `MigrationId`; Microsoft.EntityFrameworkCore.Migrations[20402]
Applying migration '20200515231101_Init-MySql'. Applying migration '20200515231101_Init-MySql'. fail:
Microsoft.EntityFrameworkCore.Database.Command[20102]
Failed executing DbCommand (181ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE `User` DROP INDEX `UserNameIndex`; Failed executing DbCommand (181ms) [Parameters=[], CommandType='Text',
CommandTimeout='30'] ALTER TABLE `User` DROP INDEX `UserNameIndex`;
MySql.Data.MySqlClient.MySqlException (0x80004005): Table
'jahan_alpha.user' doesn't exist --->
MySql.Data.MySqlClient.MySqlException (0x80004005): Table
'jahan_alpha.user' doesn't exist
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ResultSet.cs:line 49
at MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 130
at MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 391
at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\Core\CommandExecutor.cs:line 62
at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlCommand.cs:line 226
at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlCommand.cs:line 74
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Pomelo.EntityFrameworkCore.MySql.Migrations.Internal.MySqlMigrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Table 'jahan_alpha.user' doesn't exist
ApplicationDbContext:
namespace Alpha.DataAccess
{
public class ApplicationDbContext : IdentityDbContext<User, Role, int, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
// some codes...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// it should be placed here, otherwise it will rewrite the following settings!
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<RoleClaim>(builder =>
{
builder.HasOne(roleClaim => roleClaim.Role).WithMany(role => role.Claims).HasForeignKey(roleClaim => roleClaim.RoleId);
builder.ToTable("RoleClaim");
});
modelBuilder.Entity<Role>(builder =>
{
builder.ToTable("Role");
});
modelBuilder.Entity<UserClaim>(builder =>
{
builder.HasOne(userClaim => userClaim.User).WithMany(user => user.Claims).HasForeignKey(userClaim => userClaim.UserId);
builder.ToTable("UserClaim");
});
modelBuilder.Entity<UserLogin>(builder =>
{
builder.HasOne(userLogin => userLogin.User).WithMany(user => user.Logins).HasForeignKey(userLogin => userLogin.UserId);
builder.ToTable("UserLogin");
});
modelBuilder.Entity<User>(builder =>
{
builder.ToTable("User"); //.HasMany(e => e.Comments).WithOne().OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<UserRole>(builder =>
{
builder.HasOne(userRole => userRole.Role).WithMany(role => role.Users).HasForeignKey(userRole => userRole.RoleId);
builder.HasOne(userRole => userRole.User).WithMany(user => user.Roles).HasForeignKey(userRole => userRole.UserId);
builder.ToTable("UserRole");
});
modelBuilder.Entity<UserToken>(builder =>
{
builder.HasOne(userToken => userToken.User).WithMany(user => user.UserTokens).HasForeignKey(userToken => userToken.UserId);
builder.ToTable("UserToken");
});
// some codes...
}
public static async Task CreateAdminAccount(IServiceProvider serviceProvider, IConfiguration configuration)
{
UserManager<User> userManager = serviceProvider.GetRequiredService<UserManager<User>>();
RoleManager<Role> roleManager = serviceProvider.GetRequiredService<RoleManager<Role>>();
string userName = configuration["Data:AdminUser:Name"];
string email = configuration["Data:AdminUser:Email"];
string password = configuration["Data:AdminUser:Password"];
string role = configuration["Data:AdminUser:Role"];
if (await userManager.FindByNameAsync(userName) == null)
{
if (await roleManager.FindByNameAsync(role) == null)
{
await roleManager.CreateAsync(new Role(role));
}
User user = new User
{
Email = email,
UserName = userName
};
var result = userManager.CreateAsync(user, password);
if (result.IsCompletedSuccessfully)
{
await userManager.AddToRoleAsync(user, role);
}
}
}
}
}
基于执行的第一个命令是 ALTER DATABASE
这一事实,我假设 1) 当您生成初始命令时,您已经有一个带有 table User
的手动生成的数据库迁移和 2) 然后你删除了数据库 3) 然后你 运行 Update-Database
命令。
将迁移视为将数据库从一个 table 状态移动到另一个状态的增量补丁。如果你想在更新数据库时看到实际的 SQL 会是 运行,你可以发出 dotnet ef migrations script -i -o migrations.sql
命令。这将生成一个完整的脚本,其中包含从初始状态到当前状态的所有迁移。
我进一步假设您在隐藏的 // some codes...
代码块 // some codes...
某处的 ApplicationDbContext
中实际上有一个 DbSet<User>
属性
正如评论中已经指出的那样,您需要做的是;
- 从服务器
localhost
删除jahan_alpha
数据库 - 从您的项目中完全删除
Migrations
文件夹 - 运行
dotnet ef migrations add initial
- 运行
dotnet ef migrations script -i -o migrations.sql
- 验证
migrations.sql
文件中的 SQL 命令是否正确(例如CREATE DATABASE
在ALTER DATABASE
的任何实例之前) - 现在 运行
dotnet ef database update
- 这将生成jahan_alpha
数据库,其中包含代码优先项目中定义的模式