我在使用EF 5 Code First时遇到了一些麻烦,主要是因为我不知道我需要寻找什么样的行为。
这是关于编写日历后端。
日历包含CalendarEntries列表 日历由用户拥有 CalendarEntry有一个所有者(与其日历相同) CalendarEntry具有可选的邀请列表 用户拥有他所有邀请的列表。
问题是: 当我将用户添加到日历条目时,它可以工作,但是当想要将同一用户添加到另一个条目时,第一个日历条目会丢失用户(CalendarEnty.Invitees)
另一方面,正确列出了用户的邀请数量,并且邀请表也具有正确的值。
有关如何解决此问题的任何提示?
public class Calendar
{
[Key]
public int CalendarId { get; set; }
[Required]
public virtual User Owner { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<CalendarEntry> CalendarEntries { get; set; }
}
public class CalendarEntry
{
public CalendarEntry()
{
Invitees = new List<User>();
}
public virtual ICollection<User> Invitees { get; set; }
public bool IsEmpty
{
get
{
if (Invitees.Count == 0)
{
return true;
}
return false;
}
}
[Key]
public int CalendarEntryId { get; set; }
[Required]
public DateTime StartDate { get; set; }
[Required]
public DateTime EndDate { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public double Duration
{
get
{
return EndDate.Subtract(StartDate).TotalMinutes;
}
}
public int OwnerId { get; set; }
public virtual User Owner { get; set; }
public int CalendarId { get; set; }
public virtual Calendar Calendar { get; set; }
public virtual Room Room { get; set; }
}
public class Invite
{
[Key]
public int InviteId { get; set; }
public virtual CalendarEntry CalendarEntry { get; set; }
public int Accepted { get; set; }
public virtual User Owner {get; set;}
}
public class User
{
[Key]
public int UserId { get; set; }
[Required]
public string GivenName { get; set; }
[Required]
public string Surname { get; set; }
[Required]
public string MailAddress { get; set; }
public string PhoneNumber { get; set; }
public virtual Calendar Calendar { get; set; }
public int? CalendarId { get; set; }
//SHA512Hashed
private string _password = null;
public string Password
{
get
{
return _password;
}
set
{
_password = value;
}
}
public virtual ICollection<Group> Groups { get; set; }
public virtual ICollection<Invite> Invites { get; set; }
}
用户和邀请的ID用于更轻松地从WCF服务访问项目 这就是为什么我没有使用组合键
使用以下方法我确保用户只添加一次,我怀疑这会造成一些麻烦吗?不幸的是,我真的不知道如何解决它。
public int AddUser(User dbUser)
{
var users = this.GetAllUser();
if (users != null && users.Where(p => p.MailAddress == dbUser.MailAddress).Count() > 0)
{
return 0;
}
try
{
_calendarDatabase.User.Add(dbUser);
_calendarDatabase.SaveChanges();
return dbUser.UserId;
}
catch (Exception ex)
{
_logger.Error(ex.ToString());
}
return 0;
}
答案 0 :(得分:1)
您没有显示您的用户模型,但我怀疑您尚未声明对其中的(一组)CalendarEntry模型的引用。确保你已经声明它:
public class User
{
public ICollection<CalendarEntry> CalendarEntries { get; set; }
// ... other User properties
}
如果省略此引用,则EF将假定CalendarEntry与User之间的关系是多对一的,这意味着任何给定的User只能与单个CalendarEntry关联(尽管每个CalendarEntry可能有多个Users) 。因此,当您将用户分配给CalendarEntry时,它将从以前的任何关系中删除。
通过在User
模型中输入导航属性(作为集合),您告诉EF实际上这种关系是多对多的,在这种情况下它会为您生成一个映射表在幕后允许用户与任意数量的CalendarEntries相关联。
编辑 -
如果在EF中有多对多关系,则可以显式指定关系的映射表,或者让EF根据您在对象中定义的导航属性为您生成表。通过在每个引用另一个对象的对象中放置一个集合属性,EF可以推断多对多关系并采取相应的行动。
如果您有关于该关系的其他信息,例如指示User
是否已接受代码中的Invite
的{{1}},则需要指定映射表显式。执行此操作时,在EF中对其进行编码的最简单方法是让关系的每个参与方都有一个导航属性,该属性是对映射对象的集合的引用,而不是关系中的其他对象。
因此,在您的情况下,CalendarEntry
中的这一行:
CalendarEntry
应该是:
public virtual ICollection<User> Invitees { get; set; }
获取您期望的行为(例如,通过Invite映射对象让public virtual ICollection<Invite> Invitations { get; set; }
与多个CalendarEntry对象相关)。