【问题标题】:One to many relationship in Code first代码优先中的一对多关系
【发布时间】:2017-03-28 17:56:39
【问题描述】:

我想在UsersNotifications 之间创建一个我认为是一对多关系的关系。

我遇到了这个问题,不知道我哪里出错了。下面是这两个类的代码:

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }

    public virtual ICollection<Notification> Notifications { get; set; }
}

public class Notification
{
    public int NotificationID { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public DateTime Time { get; set; }

    public string ApplicationUserID { get; set; }
    public virtual ApplicationUser ApplicationUser { get; set; }
}

我上面还有以下映射:

modelBuilder.Entity<Notification>()
    .HasRequired<ApplicationUser>(u => u.ApplicationUser)
    .WithMany(u => u.Notifications)
    .HasForeignKey(u => u.NotificationID);

我在尝试修复此问题时遇到了不同的错误,例如:

  • 多重性无效
  • 违反了多重性约束。关系_的角色_具有多重性1或0..1

编辑:

当我尝试为所有用户添加通知时,抛出相同的异常(违反多重约束。关系 Notification_ApplicationUser 的角色“Notification_ApplicationUser_Target”具有多重性 1 或 0..1。)正如我在此方法中所做的那样:

public void AddNotification(Notification n)
{
    var roleId = context.Roles.Where(m => m.Name == "User").Select(m => m.Id).SingleOrDefault();
    var users = context.Users.Where(u => u.Roles.All(r => r.RoleId == roleId)).ToList();
    try
    {
        foreach(var user in users)
        {
            user.Notifications.Add(n);
        }
        context.SaveChanges();
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}

【问题讨论】:

    标签: asp.net-mvc entity-framework ef-code-first asp.net-identity


    【解决方案1】:

    我认为问题出在外键的字符串类型上。默认情况下,字符串在数据库级别可以为空,但必需的外键不能为空。指定HasRequired 仅强制要求关系是必需的,而不是外键属性必须不为空。我认为,如果您只是将 [Required] 添加到您的外键属性中,那将解决问题:

    [Required]
    public string ApplicationUserID { get; set; }
    

    显然,您需要进行迁移才能将此更改应用到您的数据库。

    编辑

    对不起,我读错了异常。您的问题的根源实际上是向每个用户添加相同的通知,就像字面上相同的通知一样。 EF做对象跟踪,所以n引用的实体实例被添加一次后,就被EF跟踪了。然后,当您尝试将其添加到另一个用户时,它认为您正在尝试进行多对多操作,基本上,单个 Notification 记录将属于多个用户。

    在我的脑海中,我不确定在 EF 中解决这种混乱的最佳方法是什么,但我有几个潜在的想法:

    1. 添加实体后可以尝试分离:

      user.Notifications.Add(n);
      context.Entry(n).State = EntityState.Detached;
      

      但是,我不确定这是否会允许添加它。你必须进行测试。如果它没有创建它,您也可以在分离之前尝试保存。我认为这可行,但每次迭代都提交数据库显然效率很低。

    2. 最安全的方法是为每个实例创建一个新实例,然后简单地映射来自n 的数据:

      var notification = new Notification
      {
          Title = n.Title,
          Description = n.Description,
          Time = n.Time
      };
      user.Notifications.Add(notification);
      

      这将确保您添加的每个通知都是一个完全独立的跟踪实例。

    【讨论】:

    • 我应用了此更改并添加了您所说的迁移,但仍然出现相同的错误(违反了多重性约束。关系“Project.DAL.Notification_ApplicationUser”的角色“Notification_ApplicationUser_Target”具有多重性1或0 ..1)
    • 克里斯你救世主。谢谢你的时间。每次这对我来说最有意义时,我都选择创建一个新实例,并为我彻底解决了问题,并且此方法不再触发任何异常。
    • 对于它的价值,这可能就是为什么这首先是一个问题。您基本上是在尝试将一对多视为多对多,这就是 EF 感到困惑的原因。如果关系是多对多的,并且您也不会有一堆基本上重复的通知记录,则不需要这些额外的代码。
    • 您只需像往常一样添加它。您的收藏将只是一个收藏。
    • UserNotifications 是您的 M2M 连接表;你不会直接使用那个。要获取特定用户的通知,您可以访问该用户的Notifications 集合,即user.Notifications,也可以查询与该用户有关系的通知:db.Notifications.Where(m =&gt; m.Users.Any(u =&gt; u.Id == userId))
    【解决方案2】:

    这是您关系的正确配置:

        modelBuilder.Entity<Notification>()
                    .HasRequired(u => u.ApplicationUser)
                    .WithMany(u => u.Notifications)
                    .HasForeignKey(u => u.ApplicationUserID);
    

    HasForeignKey 方法中,您需要指定该关系的FK,而不是Notification 实体的PK。

    更新

    问题是您的数据库中存在一对一的关系,并且您正尝试在模型中配置一对多的关系。如果最后一个是您真正想要的,那么我建议您使用Migrations 更改您的数据库架构,否则您可以这样配置您的关系:

        modelBuilder.Entity<Notification>()
                    .HasRequired(u => u.ApplicationUser)
                    .WithOptional(u => u.Notification)
    

    并更改ApplicationUser实体中的导航属性:

    public class ApplicationUser : IdentityUser
    {
           public string FirstName { get; set; }
    
           public virtual Notification Notification { get; set; }
    }
    

    【讨论】:

    • 您好,感谢您的回答,能否请您查看我更新的问题
    • 那些表已经存在于您的数据库中?因为异常说的是1-1关系
    • 这就是问题所在(我认为)。真正的关系是一对一的,而您正在尝试配置一对多
    • 所以它期望的当前关系是一对一的,而我试图在桌面上强加的是一对多?有没有办法解决这个问题?
    • 所以如果我以这种方式更新我的模型,它会给我一个一对多的关系吗?就像我的原始模型有一个 ICollection,我相信它存储了与用户关联的通知集合?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    相关资源
    最近更新 更多