-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
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.
Steps to reproduce
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; }
}Here is the AppContext.
public class AppContext: DbContext
{
private readonly IHttpContextAccessor _httpContextAccessor;
private ILoggerFactory GetLoggerFactory()
{
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(builder =>
builder.AddConsole()
.AddFilter(DbLoggerCategory.Database.Command.Name,
LogLevel.Information));
return serviceCollection.BuildServiceProvider()
.GetService<ILoggerFactory>();
}
public AppContext(DbContextOptions<AppContext> options, IHttpContextAccessor httpContextAccessor) : base(options)
{
_httpContextAccessor = httpContextAccessor;
}
public DbSet<Profile> Profiles { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder
.UseLoggerFactory(GetLoggerFactory())
.EnableSensitiveDataLogging(true);
}
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Profile>(ConfigureProfile);
builder.Entity<ProfileContact>(ConfigureProfileContact);
}
private void ConfigureProfile(EntityTypeBuilder<Profile> builder)
{
builder.Property(p => p.BrandName)
.IsRequired()
.HasMaxLength(50);
builder.OwnsOne(p => p.ProfileContact);
}
private void ConfigureProfileContact(EntityTypeBuilder<ProfileContact> builder)
{
builder.Property(pc => pc.Email)
.IsRequired()
.HasMaxLength(50);
builder.Property(pc => pc.Phone)
.IsRequired()
.HasMaxLength(10);
builder.Property(pc => pc.Mobile)
.IsRequired()
.HasMaxLength(10);
}
}I have configured ProfileContact as owned by Profile entity.
Here is the AppIdentityDbContext.
public class AppIdentityDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
{
public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
builder.Entity<ApplicationUser>().ToTable("Users", "Account");
builder.Entity<ApplicationRole>().ToTable("Roles", "Account");
builder.Entity<IdentityUserRole<Guid>>().ToTable("UserRoles", "Account");
builder.Entity<IdentityUserClaim<Guid>>().ToTable("UserClaims", "Account");
builder.Entity<IdentityUserLogin<Guid>>().ToTable("UserLogins", "Account");
builder.Entity<IdentityUserToken<Guid>>().ToTable("UserTokens", "Account");
builder.Entity<IdentityRoleClaim<Guid>>().ToTable("RoleClaims", "Account");
}
}Whenever I try to run seeding, I'm getting the same error when user logs in.
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.
Further technical details
EF Core version: 2.2.6
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: ASP.NET Core 2.2
Operating system: Windows 10 x64
IDE: Visual Studio 2017 15.9.16

