我想创建Users
和Notifications
之间的关系,我认为这种关系是一对多的关系。
我遇到了这个问题而不确定我是怎么回事。以下是两个类的代码:
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);
我在尝试解决此问题时遇到了不同的错误,例如:
编辑:
同样的异常(违反了多重性约束。当我尝试为所有用户添加通知时,抛出Notification_ApplicationUser&#39;具有多重性1或0..1。)的角色&#39; Notification_ApplicationUser_Target&#39;我用这种方法完成了它:
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);
}
}
答案 0 :(得分:3)
我认为问题来自外键的字符串类型。默认情况下,字符串在数据库级别可以为空,但必需的外键不能为空。指定HasRequired
仅强制要求关系,而不是外键属性必须不为null。我想如果您只是将[Required]
添加到您的外键属性,那将解决问题:
[Required]
public string ApplicationUserID { get; set; }
显然,您需要进行迁移才能将此更改应用于您的数据库。
修改强>
抱歉,我读错了。您的问题的根源实际上是向每个用户添加相同的通知,就像在字面上相同的通知一样。 EF进行对象跟踪,因此在n
引用的实体实例添加一次后,EF会跟踪它。然后,当您尝试将其添加到其他用户时,它会认为您尝试执行多对多,基本上,单个Notification
记录将属于多个用户。
在我的头脑中,我不确定在EF中解决这种困惑的最佳方法是什么,但我有几个潜在的想法:
添加后可以尝试分离实体:
user.Notifications.Add(n);
context.Entry(n).State = EntityState.Detached;
但是,我不确定是否允许添加它。你必须测试。如果它没有创建它,您也可以在分离之前尝试保存。我认为这样可行,但显然每次迭代都会对数据库提交效率很低。
最安全的方法是为每个实例创建一个新实例,并简单地映射来自n
的数据:
var notification = new Notification
{
Title = n.Title,
Description = n.Description,
Time = n.Time
};
user.Notifications.Add(notification);
这将确保您添加的每个通知都是完全独立的跟踪实例。
答案 1 :(得分: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; }
}