c# - 一对多关系,数据未在数据库中播种
问题描述
我从它正常工作的地方得到了这段代码。Department 类和 ApplicationUser 类具有一对多的关系。我正在尝试播种数据。角色被添加到数据库中,但不是用户或部门。这是 ApplicationUser 类
public class ApplicationUser : IdentityUser<int>
{
//n-1 relationship
public int DepartmentId { get; set; }
public Department Department { get; set; }
[DisplayName("First Name")]
[Required, MaxLength(50, ErrorMessage = "Name cannot exceed 50 characters")]
public string FirstName { get; set; }
[DisplayName("Middle Name")]
public string MiddleName { get; set; }
[DisplayName("Last Name")]
[Required]
public string LastName { get; set; }
}
这是部门班
public class Department : Entity
{
public string Name { get; set; }
public ICollection<ApplicationUser> Employees { get; set; }
}
这是上下文类
public class ManageContext : IdentityDbContext<ApplicationUser,IdentityRole<int>,int>
{
public ManageContext(DbContextOptions<ManageContext> dbContextOptions) :base(dbContextOptions)
{
}
public DbSet<Department> Departments { get; set; }
//the name of the table will be same as the name of the class
private static void SetTableNamesAsSingle(ModelBuilder builder)
{
// Use the entity name instead of the Context.DbSet<T> name
foreach (var entityType in builder.Model.GetEntityTypes())
{
builder.Entity(entityType.ClrType).ToTable(entityType.ClrType.Name);
}
}
protected override void OnModelCreating(ModelBuilder builder)
{
SetTableNamesAsSingle(builder);
base.OnModelCreating(builder);
}
}
有 2 个单独的类来播种数据。它们中有静态方法来播种和创建角色和用户。这是用于为部门类播种的 dataseeder 类
public class DataSeeder
{
public static async Task SeedAsync(ManageContext manageContext, ILoggerFactory loggerFactory, int? retry = 0)
{
int retryForAvailability = retry.Value;
try
{
await SeedDepartmentAsync(manageContext);
}
catch (Exception exception)
{
if (retryForAvailability < 10)
{
retryForAvailability++;
var log = loggerFactory.CreateLogger<ManageContext>();
log.LogError(exception.Message);
await SeedAsync
(manageContext, loggerFactory, retryForAvailability);
}
throw;
}
}
private static async Task SeedDepartmentAsync(ManageContext manageContext)
{
if (manageContext.Departments.Any())
return;
var department = new List<Department>()
{
new Department() { Name ="HR"},
new Department() { Name = "IT"}
};
manageContext.Departments.AddRange(department);
await manageContext.SaveChangesAsync();
}
}
这是创建角色和用户并填充数据库的 identityseeder 类
public class IdentitySeeder
{
#region Public Methods
public static void Seed(
ManageContext manageContext,
RoleManager<IdentityRole<int>> roleManager,
UserManager<ApplicationUser> userManager
)
{
// Create default Users (if there are none)
if (!manageContext.Users.Any())
{
CreateUsers(manageContext, roleManager, userManager)
.GetAwaiter()
.GetResult();
}
}
#endregion
#region Seed Methods
private static async Task CreateUsers(
ManageContext manageContext,
RoleManager<IdentityRole<int>> roleManager,
UserManager<ApplicationUser> userManager)
{
// local variables
DateTime createdDate = new DateTime(2021, 03, 17, 12, 30, 00);
DateTime lastModifiedDate = DateTime.Now;
string role_Administrator = "Administrator";
string role_RegisteredUser = "RegisteredUser";
//Create Roles (if they doesn't exist yet)
if (!await roleManager.RoleExistsAsync(role_Administrator))
{
await roleManager.CreateAsync(new IdentityRole<int>(role_Administrator));
}
if (!await roleManager.RoleExistsAsync(role_RegisteredUser))
{
await roleManager.CreateAsync(new IdentityRole<int>(role_RegisteredUser));
}
// Create the "Admin" ApplicationUser account
var user_Admin = new ApplicationUser()
{
SecurityStamp = Guid.NewGuid().ToString(),
FirstName = "Breta",
LastName = "Collins",
Role = "Administrator",
Email = "bretacollins@mail.com",
UserName = "breta.collins",
};
// Insert "Admin" into the Database and assign the "Administrator" and "Registered" roles to him.
if (await userManager.FindByIdAsync(user_Admin.Id.ToString()) == null)
{
await userManager.CreateAsync(user_Admin, "Password1!");
await userManager.AddToRoleAsync(user_Admin, role_Administrator);
// Remove Lockout and E-Mail confirmation.
user_Admin.EmailConfirmed = true;
user_Admin.LockoutEnabled = false;
}
await manageContext.SaveChangesAsync();
}
#endregion
}
}
这是程序类
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
SeedDatabase(host);
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
private static void SeedDatabase(IWebHost host)
{
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
try
{
var manageContext = services.GetRequiredService<ManageContext>();
var roleManager = services.GetRequiredService<RoleManager<IdentityRole<int>>>();
var userManager = services.GetRequiredService<UserManager<ApplicationUser>>();
IdentitySeeder.Seed(manageContext ,roleManager ,userManager);
}
catch (Exception exception)
{
var logger = loggerFactory.CreateLogger<Program>();
logger.LogError(exception, "An error occurred seeding the DB.");
Console.WriteLine(exception);
}
}
}
}
我是新手,并将其作为我的学习项目。我得到的错误是“INSERT 语句与 FOREIGN KEY 约束“FK_AspNetUsers_Department_DepartmentId”冲突。冲突发生在数据库“ManageDatabase”、表“dbo.Department”、列“ID”中。语句已终止。” 我不知道如何解决这个错误。谢谢您的帮助。
解决方案
您必须在播种 ApplicationUser 之前播种 Department 表。由于 DepartmentId 不可为空,因此您必须将 DepartmentId 分配给新的 ApplicationUser 实例:
var user_Admin = new ApplicationUser()
{
SecurityStamp = Guid.NewGuid().ToString(),
FirstName = "Breta",
LastName = "Collins",
Role = "Administrator",
Email = "bretacollins@mail.com",
UserName = "breta.collins",
DepartmentId=1 //or what you need
};
或者您可以更改 DepartmentId 类型
public int? DepartmentId { get; set; }
但在这种情况下,您的 Db 表的 DepartmentId 列也应该为空。
推荐阅读
- javascript - React setState 在 es6 中不可变:无法将 undefined 或 null 转换为对象
- selectize.js - selectize.js lockOptgroupOrder 抛出异常
- kendo-ui - Kendo Virtual ComboBox:选中的dataItem为null,不在bar中显示,但在datasource中存在
- ruby-on-rails - 如何在 Rails 应用程序中存储或保存内存加载的图像
- ssh - 无法 ssh 登录到 bitbucket.org
- html - 让 HTML 表格“挤压”
- ios - 在 App Store Connect 中更改现有 IAP 自动续订订阅
- bash - 如何防止执行 shell 命令?
- powershell - 需要使用 powershell 将文件中的 \x0d\x0a 替换为 \x2c\x0d\x0a
- javascript - 从一个组件对服务进行ajax调用并从另一个组件访问响应