C# ASP.NET MVC中的多对多关系错误
我是ASP.NET MVC新手,我正在创建一个用于参加音乐活动的应用程序。有一个按钮供用户跟随艺术家获取所有即将到来的活动 单击该按钮时,我得到一个错误: “ApplicationDbContext.followers”中的实体参与“ApplicationUser\u followeres”关系。找到0个相关的“ApplicationUser\u Followees\u Source”。一, 这是模型的代码:C# ASP.NET MVC中的多对多关系错误,c#,asp.net-mvc,entity-framework,many-to-many,dto,C#,Asp.net Mvc,Entity Framework,Many To Many,Dto,我是ASP.NET MVC新手,我正在创建一个用于参加音乐活动的应用程序。有一个按钮供用户跟随艺术家获取所有即将到来的活动 单击该按钮时,我得到一个错误: “ApplicationDbContext.followers”中的实体参与“ApplicationUser\u followeres”关系。找到0个相关的“ApplicationUser\u Followees\u Source”。一, 这是模型的代码: public class Following { public Applica
public class Following
{
public ApplicationUser Followers { get; set; }
public ApplicationUser Followees { get; set; }
[Key]
[Column(Order = 1)]
public string FollowerId { get; set; }
[Key]
[Column(Order = 2)]
public string FolloweeId { get; set; }
}
这是fluent api构建数据的代码:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Following> Followings { get; set; }
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ApplicationUser>()
.HasMany(u => u.Followers)
.WithRequired(f => f.Followees)
.WillCascadeOnDelete(false);
modelBuilder.Entity<ApplicationUser>()
.HasMany(u => u.Followees)
.WithRequired(f => f.Followers)
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
}
}
这是主页的前端代码,其中包含以下按钮:
@model Gighub.ViewModels.GigsViewModel
@{
ViewBag.Title = "Home Page";
}
<ul class="gigs">
@foreach (var gig in Model.UpComingGigs)
{
<li>
<div class="details">
<span class="artist">
@gig.Artist.Name @if (Model.ShowActions) {
<button class="btn btn-link btn-sm js-toggle-following" data-user-id="@gig.ArtistId">Follow?</button>
}
</span>
</div>
</li>
}
</ul>
@section scripts {
<script>
$(document).ready(function () {
$(".js-toggle-following").click(function (e) {
var btn = $(e.target);
$.post("/api/followings", { "FolloweeId": btn.attr("data-user-id") })
.done(function () {
btn.text("following")
})
.fail(function () {
alert("something failed");
});
});
});
</script>
}
@model Gighub.ViewModels.GigsViewModel
@{
ViewBag.Title=“主页”;
}
@foreach(模型中的var gig.UpComingGIG)
{
-
@gig.Artist.Name@if(Model.ShowActions){
跟着?
}
}
@节脚本{
$(文档).ready(函数(){
$(“.js切换如下”)。单击(函数(e){
var btn=$(e.target);
$.post(“/api/followers”,{“followereId”:btn.attr(“数据用户id”)})
.done(函数(){
btn.文本(“以下”)
})
.fail(函数(){
警惕(“失败的东西”);
});
});
});
}
下面是applicationuser类:
public class ApplicationUser : IdentityUser
{
public ICollection<Following> Followers { get; set; }
public ICollection<Following> Followees { get; set; }
public ApplicationUser()
{
Followers = new Collection<Following>();
Followees = new Collection<Following>();
}
[Required]
[StringLength(100)]
public string Name { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
公共类应用程序用户:IdentityUser
{
公共ICollection Followers{get;set;}
公共ICollection跟随{get;set;}
公共应用程序用户()
{
Followers=新集合();
Followees=新集合();
}
[必需]
[长度(100)]
公共字符串名称{get;set;}
公共异步任务GenerateUserIdentityAsync(用户管理器)
{
//注意authenticationType必须与CookieAuthenticationOptions.authenticationType中定义的类型匹配
var userIdentity=wait manager.CreateIdentityAsync(这是DefaultAuthenticationTypes.ApplicationOkie);
//在此处添加自定义用户声明
返回用户身份;
}
}
用以下内容替换数据库上下文:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Following>(entity =>
{
entity.HasOne(d => d.Followee )
.WithMany(p => p.Followees )
.HasForeignKey(d => d.FolloweeId)
.OnDelete(DeleteBehavior.ClientSetNull);
entity.HasOne(d => d.Follower )
.WithMany(p => p.Followers )
.HasForeignKey(d => d.FollowerId );
});
base.OnModelCreating(modelBuilder);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity(Entity=>
{
entity.HasOne(d=>d.Followee)
.有许多(p=>p.Followees)
.HasForeignKey(d=>d.followeid)
.OnDelete(DeleteBehavior.ClientSetNull);
entity.HasOne(d=>d.Follower)
.有许多(p=>p.追随者)
.HasForeignKey(d=>d.FollowerId);
});
基于模型创建(modelBuilder);
}
检查你的数据库。可能您需要重新迁移。从异常情况来看,问题似乎出现在ApplicationUser类上,并映射以下内容。如果这是EF6或EF Core 5,您可以使用以下内容:
public class ApplicationUser
{
// ...
public virtual ICollection<ApplicationUser> Followers { get; set; } = new List<ApplicationUser>();
public virtual ICollection<ApplicationUser> Followees { get; set; } = new List<ApplicationUser>();
}
公共类应用程序用户
{
// ...
公共虚拟ICollection Followers{get;set;}=new List();
公共虚拟ICollection followes{get;set;}=new List();
}
必须明确映射此关系:
(EF6)
modelBuilder.Entity()
.HasMany(u=>u.Followers)
.有许多(u=>u.Followees)
.Map(u=>u.ToTable(“以下”)
.MapLeftKey(“FollowerId”)
.MapRightKey(“followeId”))
.WillCascadeOnDelete(假);
EF Core的映射将略有不同,但应该能够遵循相同的要点,只需要检查EF Core 5支持非声明链接实体的多对多设置
或者,您可以使用“以下”实体(EF Core<5所需)将其映射出来,但这在某种程度上改变了关系,因为它更像是多对一对多,而不是多对多:
public class ApplicationUser
{
// ...
public virtual ICollection<Following> FollowingsAsFollower { get; set; } = new List<Following>();
public virtual ICollection<Following> FollowingsAsFollowee { get; set; } = new List<Following>();
}
public class Following
{
[Key, Column(Order=0), ForeignKey("Follower")]
public int FollowerId {get; set;}
[Key, Column(Order=1), ForeignKey("Followee")]
public int FolloweeId {get; set;}
public virtual ApplicationUser Follower { get; set; }
public virtual ApplicationUser Followee { get; set; }
}
公共类应用程序用户
{
// ...
公共虚拟ICollection{get;set;}=new List();
公共虚拟ICollection followee{get;set;}=new List();
}
公开课跟风
{
[键,列(顺序=0),外键(“跟随者”)]
公共int FollowerId{get;set;}
[Key,Column(Order=1),ForeignKey(“Followee”)]
公共int followeId{get;set;}
公共虚拟应用程序用户跟随者{get;set;}
公共虚拟应用程序用户Followee{get;set;}
}
映射结果如下所示:
modelBuilder.Entity<Following>()
.HasRequired(u => u.Follower)
.WithMany(u => u.FollowingsAsFollower)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Following>()
.HasRequired(u => u.Followee)
.WithMany(u => u.FollowingsAsFollowee)
.WillCascadeOnDelete(false);
modelBuilder.Entity()
.HasRequired(u=>u.Follower)
.有许多(u=>u.S)
.WillCascadeOnDelete(假);
modelBuilder.Entity()
.HasRequired(u=>u.Followee)
.有许多(u=>u.followee)
.WillCascadeOnDelete(假);
对于链接表,这看起来很奇怪,因为我们正在映射多对多自引用。我混合了属性和modelBuilder之间的配置,但是由于自引用类型,您至少需要一些显式的modelBuilder/EntityTypeConfiguration映射用于关系。EF自动映射关系的约定基于导航属性类型而不是属性名称,因此为同一类型设置多个关系需要明确
问题可能是试图在用户中为追随者/追随者设置单个追随者。此自引用关系需要有两个集合,因为“以下”表希望其一端的FollowerID与另一端集合中的FollowerID之间存在直接关系。两个表之间建立的多对多关系在每个表上都有集合,这样一个学生将列出所有课程,一个课程将列出所有学生。带着一个sel
modelBuilder.Entity<ApplicationUser>()
.HasMany(u => u.Followers)
.WithMany(u => u.Followees)
.Map(u => u.ToTable("Followings")
.MapLeftKey("FollowerId")
.MapRightKey("FolloweeId"))
.WillCascadeOnDelete(false);
public class ApplicationUser
{
// ...
public virtual ICollection<Following> FollowingsAsFollower { get; set; } = new List<Following>();
public virtual ICollection<Following> FollowingsAsFollowee { get; set; } = new List<Following>();
}
public class Following
{
[Key, Column(Order=0), ForeignKey("Follower")]
public int FollowerId {get; set;}
[Key, Column(Order=1), ForeignKey("Followee")]
public int FolloweeId {get; set;}
public virtual ApplicationUser Follower { get; set; }
public virtual ApplicationUser Followee { get; set; }
}
modelBuilder.Entity<Following>()
.HasRequired(u => u.Follower)
.WithMany(u => u.FollowingsAsFollower)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Following>()
.HasRequired(u => u.Followee)
.WithMany(u => u.FollowingsAsFollowee)
.WillCascadeOnDelete(false);