.NET Core 将多个实体关联到一个用户
.NET Core associate multiple enteties to a user
我正在尝试关联用户和 class 之间的一对多关系。当我尝试创建一个 Post 时,我也在尝试将它添加到用户模型中,但我似乎做不对。
应该可以拥有多个项目实体的用户
public class AppUser : IdentityUser
{
public ICollection<UserProject> Projects { get; set; }
}
项目模型
public class UserProject
{
public int Id { get; set; }
public string Name { get; set; }
}
添加项目并将其与用户关联的操作
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(UserProject userProject)
{
if (ModelState.IsValid)
{
AppUser appUser = await userManager.GetUserAsync(HttpContext.User);
appUser.Projects.Add(userProject);
context.Projects.Add(userProject);
await context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(userProject);
}
但是 context.Projects.Add(userProject);
导致错误 NullReferenceException: Object reference not set to an instance of an object.
有人可以告诉我哪里出了问题以及如何实现我想要做的事情吗?
数据库上下文
public class ScrumApplicationContext : IdentityDbContext<AppUser>
{
public ScrumApplicationContext(DbContextOptions<ScrumApplicationContext> options)
: base(options)
{
}
public DbSet<UserProject> Projects { get; set; }
}
启动配置服务
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<ScrumApplicationContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ScrumApplicationContext")));
services.AddIdentity<AppUser, IdentityRole>()
.AddEntityFrameworkStores<ScrumApplicationContext>()
.AddDefaultTokenProviders();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "areas",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
});
CreateAdminRole(serviceProvider);
CreateAdminUserAsync(serviceProvider);
}
创建视图
@model ScrumApp.Models.UserProject
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
尝试将外键添加到 User
和 Project
到 UserProject
class。
public class UserProject
{
public int Id { get; set; }
public string Name { get; set; }
public int UserId { get; set; }
public int ProjectId { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
[ForeignKey("ProjectId")]
public Project Project { get; set; }
}
然后您可以添加实体:
var userProject = new UserProject { UserId=.., ProjectId=.. };
context.UserProjects.Add(userProject);
问题是 Projects
最初为空。您需要先初始化它:
appUser.Projects ??= new List<UserProject>();
appUser.Projects.Add(userProject);
或者简单地在 属性 上设置一个默认值:
public ICollection<UserProject> Projects { get; set; } = new List<UserProject>();
至少有一个项目(并包括查询中的关系)可以解决此问题,因为 EF 已经实例化了集合。但是,这并不能解决所有情况下的问题,也不是 "solution"。您需要适当地规划和处理 null。
我正在尝试关联用户和 class 之间的一对多关系。当我尝试创建一个 Post 时,我也在尝试将它添加到用户模型中,但我似乎做不对。
应该可以拥有多个项目实体的用户
public class AppUser : IdentityUser
{
public ICollection<UserProject> Projects { get; set; }
}
项目模型
public class UserProject
{
public int Id { get; set; }
public string Name { get; set; }
}
添加项目并将其与用户关联的操作
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(UserProject userProject)
{
if (ModelState.IsValid)
{
AppUser appUser = await userManager.GetUserAsync(HttpContext.User);
appUser.Projects.Add(userProject);
context.Projects.Add(userProject);
await context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(userProject);
}
但是 context.Projects.Add(userProject);
导致错误 NullReferenceException: Object reference not set to an instance of an object.
有人可以告诉我哪里出了问题以及如何实现我想要做的事情吗?
数据库上下文
public class ScrumApplicationContext : IdentityDbContext<AppUser>
{
public ScrumApplicationContext(DbContextOptions<ScrumApplicationContext> options)
: base(options)
{
}
public DbSet<UserProject> Projects { get; set; }
}
启动配置服务
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<ScrumApplicationContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ScrumApplicationContext")));
services.AddIdentity<AppUser, IdentityRole>()
.AddEntityFrameworkStores<ScrumApplicationContext>()
.AddDefaultTokenProviders();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "areas",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
});
CreateAdminRole(serviceProvider);
CreateAdminUserAsync(serviceProvider);
}
创建视图
@model ScrumApp.Models.UserProject
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
尝试将外键添加到 User
和 Project
到 UserProject
class。
public class UserProject
{
public int Id { get; set; }
public string Name { get; set; }
public int UserId { get; set; }
public int ProjectId { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
[ForeignKey("ProjectId")]
public Project Project { get; set; }
}
然后您可以添加实体:
var userProject = new UserProject { UserId=.., ProjectId=.. };
context.UserProjects.Add(userProject);
问题是 Projects
最初为空。您需要先初始化它:
appUser.Projects ??= new List<UserProject>();
appUser.Projects.Add(userProject);
或者简单地在 属性 上设置一个默认值:
public ICollection<UserProject> Projects { get; set; } = new List<UserProject>();
至少有一个项目(并包括查询中的关系)可以解决此问题,因为 EF 已经实例化了集合。但是,这并不能解决所有情况下的问题,也不是 "solution"。您需要适当地规划和处理 null。