reach4thelasers
reach4thelasers

Reputation: 26909

Entity Framework Code First - Strange Entity Loading Behaviour

The site I'm working on employs a standard social networking Paradigm : Friends and FriendRequests.

My User and friend requests classes are as follows:

public class User
{
    public int Id { get; set; }

    public ICollection<FriendRequest> FriendRequests { get; set; }
}

public class FriendRequest
{
    public int UserId { get; set; }
    public int FriendId { get; set; }

    public DateTime RequestDate { get; set; }

    public User User { get; set; }
    public User Friend { get; set; }
}

My Fluent Mapping is:

modelBuilder.Entity<User>()
    .HasMany(u => u.FriendRequests)
    .WithRequired(f => f.User)
    .HasForeignKey(f => f.UserId);

modelBuilder.Entity<FriendRequest>()
    .HasKey(f => new { f.UserId, f.FriendId });

modelBuilder.Entity<FriendRequest>()
    .HasRequired(f => f.Friend)
    .WithMany()
    .HasForeignKey(f => f.FriendId);

I'm working with 2 of my test Users - user 22 and user 18

User 22 has a friend request in the database from user 18

UserId  FriendId    DateRequested         RequestStatus  DateResponded
22      18          2012-05-28 16:48:00   -1             NULL   

Now the weird bit:

Take this Test:

    public void FriendRequestTests()
    {
        var user22 = userRepository.FindById(22);
        Console.WriteLine(user22.FriendRequests.Count); // Count: 1

        var request = user22.FriendRequests[0];
        var friend = request.Friend; // Null
    }

The problem is that request.Friend is null (although all other values are populated)

Now run the same test again, but fetch user18 first (but do nothing with it)

    public void FriendRequestTests()
    {
                    var user18 = userRepository.FindById(18); // do nothing with this
        var user22 = userRepository.FindById(22);
        Console.WriteLine(user22.FriendRequests.Count); // Count: 1

        var request = user22.FriendRequests[0];
        var friend = request.Friend; // correct user (user18)
    }

I'm seeing this behaviour consistently with the friend requests. If the user who is the friend has been previously accessed in the session then request.Friend is not null. If the friend has never been accessed in the session then request.Friend is always null.

What's causing this weirdness and how do I fix it?
Furthermore, is there any way to define in a Mapping that a Foreign Key relation should ALWAYS be fetched by a left outer join? I know NHibernate lets you do this, but EF is new to me.

Upvotes: 0

Views: 127

Answers (1)

Patrick McCurley
Patrick McCurley

Reputation: 2054

Try setting your navigation properties to virtual

Something like

public class User
{
    public int Id { get; set; }

    public virtual ICollection<FriendRequest> FriendRequests { get; set; }
}

public class FriendRequest
{
    public int UserId { get; set; }
    public int FriendId { get; set; }

    public DateTime RequestDate { get; set; }

    public virtual User User { get; set; }
    public virtual User Friend { get; set; }
}

if you're lazy loading your ObjectContext, this could be causing your issues.

Upvotes: 2

Related Questions