C# ASP.NET MVC中的多对多关系错误

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

我是ASP.NET MVC新手,我正在创建一个用于参加音乐活动的应用程序。有一个按钮供用户跟随艺术家获取所有即将到来的活动

单击该按钮时,我得到一个错误:

“ApplicationDbContext.followers”中的实体参与“ApplicationUser\u followeres”关系。找到0个相关的“ApplicationUser\u Followees\u Source”。一,

这是模型的代码:

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);