I have model class inheriting from IdentityUser
, which has 1 to 1 relationship
public class CustomUser: IdentityUser
{
public ExtendedUserData ExtendedData { get; set; }
}
And I have an ExtendedData model class:
public class ExtendedUserData
{
public Guid Id { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Contract { get; set; }
public string ExtendedDataOfCustomUserId { get; set; }
public CustomUser CustomUser { get; set; }
}
(made this with this EF core tutorial )
But, if I use this method to get data
public ExtendedUserData GetExtendedUserDataById(Guid id)
{
return context.ExtendedUserDatas
.FirstOrDefault(x => x.ExtendedDataOfCustomUserId == id.ToString());
}
I try make like this
ExtendedUserData userData = new ExtendedUserData();
userData = GetExtendedUserDataById(id);
....
userData.CustomUser.Id;
OR
userData.CustomUser.UserName;
I get an error. like a NullRefExc
How can I get related data from ExtendedUserData
(or mb CustomUser
) using 1 to 1 relationship?
I think about this, but besides this I didn't come up with anything else
public ExtendedUserData GetExtendedUserDataById(Guid id)
{
ExtendedUserData ud = context.ExtendedUserDatas
.FirstOrDefault(x => x.ExtendedDataOfCustomUserId == id.ToString());
ud.CustomUser = context.CustomUsers
.FirstOrDefault(x => x.Id == id.ToString());
return ud;
}
Maybe this can be done more correctly or shorter?
Thanks for your answers!
If you already have the CustomUser loaded and tracked by EF, this should work. If you only have the ID, you have to take care of related data yourself. Few ways:
public ExtendedUserData GetExtendedUserDataById(Guid id)
{
return context.ExtendedUserDatas
.Include(x => x.CustomUser)
.FirstOrDefault(x => x.ExtendedDataOfCustomUserId == id.ToString())
;
}
good when you know that every consumer will want CustomUser loaded. In general code, it's difficult to tell what you need to Include in advance (CustomUser can also have related entities you may want to load, and so on, leading to long chain of .Include(...).ThenInclude(...)
).
public ExtendedUserData GetExtendedUserDataById(Guid id)
{
var user = context.ExtendedUserDatas
.FirstOrDefault(x => x.ExtendedDataOfCustomUserId == id.ToString())
;
if (user != null)
{
context.Entry(user).Reference(x => x.CustomUser).Load();
}
return user;
}
This doesn't make much sense as written. But since anyone can do it, this way you can pass responsibility to load related data to consumer who knows better what it needs. Kinda pain to write when the relation chain gets longer and includes collections.
There is also lazy loading that hides all this complexity, but you have to take some steps to activate it, and it's easy to kill your performance with it if you forget it's there. More information about all three: https://docs.microsoft.com/en-us/ef/core/querying/related-data#lazy-loading
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.