2

我在以下类之间有两个一对多的关系

public class SiteMember
{
        public int SiteMemberID { get; set; }
        public virtual List<FriendshipInvitation> InvitationsSent { get; set; }
        public virtual List<FriendshipInvitation> InvitationsReceived { get; set; }
}

public class FriendshipInvitation
{
        public int InvitingUserID { get; set; }
        public SiteMember InvitingUser { get; set; }

        public int InvitedUserID { get; set; }
        public SiteMember InvitedUser{ get; set; }
}

然后在控制器中,我有以下代码(从数据库加载一个 SiteMember):

SiteMember sm = repoSiteMember.GetUserByName(User.Identity.Name);

在此刻

sm.InvitationsReceived.InvitingUserId = 1;
sm.InvitationsReceived.InvitingUser = null

然后我有以下行(从 db 加载所有 SiteMembers):

IEnumerable<SiteMember> all = repoSiteMember.GetAll();

之后

sm.InvitationsReceived.InvitingUserId = 1 
sm.InvitationsReceived.InvitingUser = proxy to SiteMember object.

我的问题是:这是正常行为吗?我很确定我可以用 include 语句“修复”空指针,但我发现从 db 加载所有元素实际上改变了对象的状态很奇怪。(空 => 代理)。代理应该从一开始就在那里吗?

编辑: 确认一下,include 语句确实解决了空引用的问题,但这不是这里的问题。

DataContext.Members
   .Include("InvitationsSent.InvitedUser")
   .Include("InvitationsReceived.InvitingUser")
   .FirstOrDefault(e => e.UserName == userName);

Edit2:现在包括方法。

public SiteMember GetUserByName(string userName)
{
    return base.DataContext.Members.FirstOrDefault(e => e.UserName == userName);
}

public IEnumerable<SiteMember> GetAll()
{
    return base.DataContext.Members.ToList();
}

Edit3:您可能需要它来重新创建模型。

    modelBuilder.Entity<FriendshipInvitation>()
        .HasRequired(e => e.InvitedUser)
        .WithMany(e => e.InvitationsReceived)
        .HasForeignKey(e => e.InvitedUserID)
        .WillCascadeOnDelete(false);

    modelBuilder.Entity<FriendshipInvitation>()
        .HasRequired(e => e.InvitingUser)
        .WithMany(e => e.InvitationsSent)
        .HasForeignKey(e => e.InvitingUserID);


    modelBuilder.Entity<FriendshipInvitation>()
        .HasKey(e => new { e.InvitingUserID, e.InvitedUserID, e.InvitationNo });
4

1 回答 1

1

是的,不同的行为是正常的,它是由于关系修复而发生的。

当您仅SiteMember使用FirstOrDefault两个集合加载一个InvitationsSent并且InvitationsReceived将在您访问它们时立即加载(或在调试器中检查它们),因为它们被标记为virtual并且将应用延迟加载。但是FriendshipInvitation这些集合中的 s 不会延迟加载InvitingUser或 ,InvitedUser因为这些导航属性没有标记为virtual.

比如说,SiteMember您加载的 1FirstOrDefault收到了来自SiteMember2 的邀请,但没有发送邀请。因此,InvitationsReceived将包含一个元素并且InvitationsSent为空。该元素 - 一个FriendshipInvitation实体 - 将具有InvitingUser2 和InvitedUser1。在这种情况下InvitingUser将是null因为它不能被延迟加载(因为它不是virtual)并且SiteMember2 尚未加载到上下文中。(InvitedUser但是将是 1 的动态代理,SiteMember因为您已经加载了SiteMember1,请参阅下一段。)

但是,如果您加载所有 SiteMember带有 2 的 s ,ToList()也会SiteMember将其加载到由 执行的查询的上下文中ToList()。EF 会InvitingUser自动将 2 设置为已加载的实体,称为关系修复导航属性的延迟加载不会加载它,InvitingUser因为 not 属性不支持延迟加载virtual

为了保持一致的行为而不是单独依赖关系修复,我建议您也标记InvitingUserInvitedUser导航属性virtual

于 2012-10-03T13:09:45.583 回答