2

私は次のクラスの間に2つの1対多の関係があります

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

次に、コントローラーに次のコードがあります(dbから1つの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ステートメントでnullポインターを「修正」できると確信していますが、dbからすべての要素をロードすると、実際にオブジェクトの状態が変わるのは奇妙だと思います。(null =>プロキシ)。プロキシは最初からそこにあるべきですか?

編集: 確認のために、includeステートメントはnull参照の問題を解決しますが、それはここでの問題ではありませんでした。

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

はい、異なる動作は正常であり、RelationshipFixupが原因で発生します。

2つのコレクションSiteMemberを1つだけロードすると、それらにアクセスするとすぐにロードされます(または、デバッガーでそれらを検査します)。これは、それらがとしてマークされ、遅延ロードが適用されるためです。ただし、これらのナビゲーションプロパティはとしてマークされていないため、これらのコレクションのsはまたはを遅延ロードしません。FirstOrDefaultInvitationsSentInvitationsReceivedvirtualFriendshipInvitationInvitingUserInvitedUservirtual

たとえば、SiteMemberロードする1にFirstOrDefaultは、SiteMember2からの招待があり、招待は送信されていません。したがって、InvitationsReceived1つの要素が含まれ、InvitationsSent空になります。その要素(FriendshipInvitationエンティティ)はInvitingUser2とInvitedUser1InvitingUserになります。このnull場合、レイジーにロードすることはできず(ロードされていないためvirtual)、SiteMember2はまだコンテキストにロードされていないためです。(ただし、すでに1をロードしているため、1InvitedUserへの動的プロキシになります。次の段落を参照してください。)SiteMemberSiteMember

ただし、すべて SiteMemberのsを2でロードするとToList()SiteMemberによって実行されるクエリを使用してコンテキストにもロードされますToList()。EFは、 RelationshipFixupInvitingUserと呼ばれるすでにロードされているエンティティに2を自動的に設定します。notプロパティでは遅延読み込みがサポートされていないため、ナビゲーションプロパティの遅延読み込みでは読み込まれません。InvitingUservirtual

一貫した動作を実現し、Relationship Fixupだけに依存しないようにするには、ナビゲーションプロパティにもマークを付けることをお勧めInvitingUserInvitedUserますvirtual

于 2012-10-03T13:09:45.583 に答える