EF: Navigation property is null even after accessing it or removing virtual keyword

.net asp.net-core c# entity-framework-core

Question

I am new to entity framework (core), I am facing some problem related to lazy loading as I think.

I have the following simple data model with one to one relationship:

User ----- AccessToken

User:

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

    public virtual AccessToken AccessToken { get; set; }
}

AccessToken:

public class AccessToken
{
    public int Id { get; set; }
    public string Token { get; set; }

    [ForeignKey("User"), Required]
    public int UserId { get; set; }
    public virtual User User { get; set; }
}

Now when I trying to get the AccessToken of a User using the User's navigation property it is always null:

var t1 = Context.Find<User>(user.Id);
var t2 = t1.AccessToken;
var t3 = Context.Find<User>(user.Id).AccessToken;

I also tried to remove virtual keyword from the navigation properties with no success.

Would some one help me to solve that problem please?

1
0
3/6/2017 9:41:53 PM

Accepted Answer

First, this is not a 1:1 relationship. As for the database, there can be multiple AccessTokens with the same UserId, i.e. it's a 1:n relationship. To turn it into a real 1:1 relationship, your model should look like this:

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

    public virtual AccessToken AccessToken { get; set; }
}

public class AccessToken
{
    [ForeignKey("User")]
    public int Id { get; set; }
    public string Token { get; set; }

    public virtual User User { get; set; }
}

Now any AccessToken will have a PK that's identical to its User's PK, so it's unique and tied to only one user.

Next, as said in the comments, lazy loading is not yet supported in EF core. Until it is (if ever?) you have to use Include (eager loading) ...

using (var db = new MyContext())
{
    var user = db.Users.Include(u => u.AccessToken)
                 .Single(u => u.Id == 1);
}

... or load the data separately (eplicit loading):

    db.AccessTokens.Where(a => a.Id == 1).Load();
    var user = db.Users
                 .Single(u => u.Id == 1); // Or db.Users.Find(1)

In the latter case, EF will connect the user and its token by relationship fixup.

2
3/5/2017 8:44:58 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow