简体   繁体   中英

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

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?

First, this is not a 1:1 relationship. As for the database, there can be multiple AccessToken s with the same UserId , ie 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM