I'm using EF Core 2.2. I have two context in my application. One is AppIdentityDbContext
for identity related works and other is AppContext
for app related works.
I have an identity user class - ApplicationUser
- which has a relation to Profile
entity from AppContext
and the Profile
entity in turn owns a value object ProfileContact
.
Here is the code:
ApplicationUser
public class ApplicationUser : IdentityUser<Guid>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Designation { get; set; }
public Guid ProfileId { get; set; }
public Profile Profile { get; set; }
}
Profile
public class Profile : BaseEntity<Guid>, IAggregateRoot
{
private Profile()
{
// required by EF
}
public Profile(string brandName, ProfileContact profileContact)
{
BrandName = brandName;
ProfileContact = profileContact;
}
public string BrandName { get; set; }
public ProfileContact ProfileContact { get; private set; }
}
ProfileContact
public class ProfileContact // ValueObject
{
private ProfileContact()
{
// required by EF
}
public ProfileContact(string email, string phone, string mobile)
{
Email = email;
Phone = phone;
Mobile = mobile;
}
public string Email { get; private set; }
public string Phone { get; private set; }
public string Mobile { get; private set; }
}
IAggregateRoot
IAggregateRoot
is an empty interface used to restrict entities from using generic repositories in my project.
public interface IAggregateRoot
{
}
AppContext
Here is the 'Profile' Entity configuration in AppContext
.
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Profile>(ConfigureProfile);
}
private void ConfigureProfile(EntityTypeBuilder<Profile> builder)
{
builder.Property(p => p.BrandName)
.IsRequired()
.HasMaxLength(50);
builder.OwnsOne(p => p.ProfileContact);
}
I have configured ProfileContact
as owned by Profile
entity.
Now whenever user logs in, I get this error:
Here is my login Post
method. I'm using Asp.Net Core Identity scaffolded template.
Login - OnPostAsync
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.MobileNumber, Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
....
// If we got this far, something failed, redisplay form
return Page();
}
Does the value object/owned type needs an key to be defined? What I read and understood about OwnedTypes
is that they belong to the same table but can be used as object. Am I doing anything wrong? or I need to add Id
property to ProfileContact
. If so why? Please assist.
I think this issue is happening if you have two separate context. One for Application and another one for Asp.Net Identity with customized ASP.NET Identity models. And that too with relations between entities in both context.
In that case, adding base.OnModelCreating(builder)
in both the context
's OnModelCreating(ModelBuilder builder)
solves the issue.
Thanks Gert Arnold for guidance and teaching. Credits to you.