0

I'm learning to build a ASP.NET MVC Core web application. Everything works fine until I start to add Identity to it.

Registered User can create many Jobs. I use the ApplicationUser.cs that comes with the project for the User. I created another DbContext for all others entities.

ApplicationUser.cs in Model:

public class ApplicationUser : IdentityUser
{
    // CUSTOM PROPERTIES
    public string Name { get; set; }
    public ICollection<Job> Jobs { get; set; }
}

Job.cs in Model:

public class Job 
{
    public int ID { get; set; }
    public string Title { get; set; }

    // contains other properties

    public string ApplicationUserID { get; set; }
    public virtual ApplicationUser ApplicationUser { get; set; }
}

ApplicationDbContext.cs:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {

    }
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    }
}

When I add these 2 lines in Job.cs, the error pops up.

    public string ApplicationUserID { get; set; }
    public virtual ApplicationUser ApplicationUser { get; set; }

Error ==>>

Unhandled Exception: System.Exception: Could not resolve a service of type 'MyProject.Data.JobDbContext' for the parameter 'context' of method 'Configure' on type 'MyProject.Startup'. ---> System.InvalidOperationException: The entity type 'IdentityUserLogin' requires a primary key to be defined.

I know that there are some threads discussing about the same error, but those answer can't really help.

10
  • Some post says adding base.OnModelCreating statement to OnModelCreating method could solve the problem but it doesn't in my code. Commented Dec 29, 2016 at 10:04
  • reading the error i think you've not a PK in your User model ..could be? Commented Dec 29, 2016 at 10:26
  • I can't see the mappings for tables..... did you do these mappings? Commented Dec 29, 2016 at 10:26
  • @federicoscamuzzi The ApplicantionUser model is derived from IdentityUser. Isn't it got the UserId PK inherited from IdentityUser? I tried to add public int ApplicationUserId { get; set; } to the ApplicationUser but still showing the same problem... Commented Dec 29, 2016 at 10:29
  • @federico-scamuzzi, IdenityUser already has the PK, but the lack of mappings can affect the model Commented Dec 29, 2016 at 10:30

1 Answer 1

2

Your problem is two different contexts.

JobDbContext contains Job, which refers to ApplicationUser which is NOT in this context, but added by EF automatically because you linked to it. And this ApplicationUser (it's parent IdentityUser) contains collection of logins (IdentityUserLogin) which is not part of this context too, but auto-added by EF, and so on... All this classes are configured in OnModelCreating of IdentityDbContext and NOT configured in JobDbContext that's why you see this error - you have no description keys/indexes/references of this classes in JobDbContext.

You should either combine two DbContext into one, or remove public virtual ApplicationUser ApplicationUser { get; set; } from Job class and manage related object manually (ensure referential integrity, do lazy loading etc).

Sign up to request clarification or add additional context in comments.

2 Comments

It really makes sense! When I combine two DbContext into one, it works like a charm. But I really want to learn more how to manage this with two different contexts - I don't really get what you mean "manage related object manually". Could you show me some example please? As I read through some online tutorials, they usually leave ApplicationDbContext alone and create their own DbContext. Instead of one DbContext for all, it seems that having separate DbContext handling different part of entities is more neatly or separation of concern.
Imagine that two different dbcontexts may be two different physical databases, even on different DB engines. It's how EF "think" about them. All "links" between them (Job in one and User in other) exists only inside your app. EF known nothing about cross-dbcontext operation. If your app should "do not delete user if he owns at least one job" - you should write this code yourself. If you need to show list of jobs with user names - you should read jobs into List from first dbcontext, read users from other dbcontext and merge/join this lists "manually" in memory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.