none
Error when IdentityDbContext uses EDMX entities from the General Context RRS feed

  • Question

  • I have a solution divided into several projects. Part in Windows Forms and part in ASP.MVC. The structure, simplified for example, is as follows: MyProject.EF.DataBase.SQL (here is the EDMX) MyProject.WEB.MVC (here is Identity)

    The entire solution uses the context and the connection string DataBase First that is in MyProject.EF.DataBase.SQL.

    And for Identity I have created a proper string connection so that Web.config has:

    <connectionStrings>
    <add name="MyProjectEntities" connectionString="metadata=res://*/GPSd_BD.csdl|res://*/GPSd_BD.ssdl|res://*/GPSd_BD.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(LocalDb)\MSSQLLocalDB;initial catalog=GPSd;user id=sa;password=xxx;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
    <add name="IdentityConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=GPSd;user id=sa;password=xxx;" providerName="System.Data.SqlClient" />

    I used these 2 tutorials to integrate AspNetUsers with Id INT into my database. But I have a little problem, which I do not understand.

    https://danieleagle.com/2014/05/setting-up-asp-net-identity-framework-2-0-with-database-first-vs2013-update-2-spa-template/

    https://docs.microsoft.com/en-us/aspnet/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity

    All because my AspNetUsers has relationships with several other entities, so ... To refer to them in my ApplicationDbContext DbSet (Identity context), if I make a copy of the EDMX entity within the MVC Models folder, the system works perfectly. But if I try to reference entities directly from EDMX I start having a lot of erros, like:

    System.Data.Entity.ModelConfiguration.ModelValidationException: One or more validation errors were detected during model generation: GPSd.Web.MVC.Models.AspNetUserLogins: : EntityType 'AspNetUserLogins' has no key defined. Define the key for this EntityType. AspNetUserLogins: EntityType: EntitySet 'AspNetUserLogins' is based on type 'AspNetUserLogins' that has no keys defined.

    If I solve this overhide OnModelCreate I have other and other... I've never seen anything like it ... How can I solve this, so that I do not have to copy my EDMX to the Models folder?

    //using WEB.MVC.Models;   //<---If I use this Work fine!
    //using MyProject.EF.DataBase.SQL;   //<---If I use this I have validation errors were detected during model generation
    namespace GPSd.Web.MVC.Models
    {
    public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, int> manager)
        {
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            return userIdentity;
        }
    
        public string LOGIN { get; set; }
        //public int IDUNIDADE { get; set; } By test I'm trying only 1 relation for time
        //public int IDPESSOA { get; set; }
    
        [ForeignKey("STATUS_REGISTROS")]
        public int IDSTATUSREGISTRO { get; set; }
    
        public virtual STATUS_REGISTROS STATUS_REGISTROS { get; set; }
    
    }
    
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>
    {
        public ApplicationDbContext()
            : base("IdentityConnection")
        {
        }
    
        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    
        public virtual DbSet<STATUS_REGISTROS> STATUS_REGISTROS { get; set; }
    } 
    }

    Edited here ------------------------------------------

    Looking back, I realized that what I said was not entirely correct. Because when I copied the EDMX entity, I removed the virtual ICollection methods to simplify the example. It turns out that one of these ICollection refers to a relationship from the AspNetUsers table.

    By doing more tests and according to the relationships of my system I realized that when one of the Identity tables is mentioned, then I get my errors:

    -ApplicationUser 'and' AspNetUsers' can not share table 'AspNetUsers'

    -'AspNetUserLogins' dont have a key definition

    - etc, etc

    Adding the code of such entity I am copying:

    public partial class STATUS_REGISTROS
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public STATUS_REGISTROS()
        {
            this.AspNetUsers = new HashSet<AspNetUsers>();
            this.HOLDINGS_GRUPOS = new HashSet<HOLDINGS_GRUPOS>();
            this.UNIDADES = new HashSet<UNIDADES>();
        }
    
        public int ID { get; set; }
        public string DESCRICAO { get; set; }
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<AspNetUsers> AspNetUsers { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<HOLDINGS_GRUPOS> HOLDINGS_GRUPOS { get; set; }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<UNIDADES> UNIDADES { get; set; }
    }

    • Edited by AlamBique Thursday, November 23, 2017 1:44 PM Adding New Findings to Explanation
    Thursday, November 23, 2017 11:10 AM

Answers

  • How can I join my GenralContext and my EntityContex? I want to use the AspnetUsers table as my User table.

    You can't join is the bottom line here you cant join the two contexts.

    I don't understand this.

    I'll assume that the MVC solution is allowing the user to logon to the application, and at that point, you know the user's credentials and you have the ability at that point to get the ID property from AspnetUsers for the logged-in user. 

    So, you should be able to take the ASPnetUsers ID and apply it  to any table where you are trying to crate some kind of relationship, a logical relationship, based on the known ID of the logged-on user with the ID for the user obtained from ASPnetUsers.

    • Marked as answer by AlamBique Friday, November 24, 2017 11:12 PM
    Friday, November 24, 2017 7:14 PM

All replies

  • All because my AspNetUsers has relationships with several other entities, so ... To refer to them in my ApplicationDbContext DbSet (Identity context), if I make a copy of the EDMX entity within the MVC Models folder, the system works perfectly. But if I try to reference entities directly from EDMX I start having a lot of erros, like:

    What are you talking about? So it works when the model is used in the MVC solution for Identity. But when you try to reference the model? Reference it for what purpose? Why? What are you trying to do here? Are you trying to get the Windows solution to use Identity?

    Thursday, November 23, 2017 1:44 PM
  • What are you trying to do here? Are you trying to get the Windows solution to use Identity?

    Sorry if I was not clear. I'm confused myself.
    I just have 2 context sharing entities. For better understanding ... One containing my entire bank for general application use. And a second context inheriting IdentityDbContext for use of Identity. Now in this second context I want to reuse the POCO entities generated by the Entity Framework DataBase First.
    When I put "virtual public DbSet <STATUS_REGISTROS> STATUS_REGISTROS {get; set;}" in the second context this entity STATUS_REGISTROS was automatically generated by the Entity Framework DataBase First. I just want to reuse it without having to copy it to the Models folder.


    Please see I add information in my question. The problem seems to be some kind of conflict between the entities in my General Context that refer to AspNetUsers, AspNetRoles, etc. and those in IdentityContext.
    • Edited by AlamBique Thursday, November 23, 2017 2:00 PM add information
    Thursday, November 23, 2017 1:57 PM
  • Please see I add information in my question. The problem seems to be some kind of conflict between the entities in my General Context that refer to AspNetUsers, AspNetRoles, etc. and those in IdentityContext.

    You can't go across contexts/virtual models with EF.

    Why are you trying to do it? What's the purpose?

    Thursday, November 23, 2017 7:23 PM
  • DA924x How can I join my GenralContext and my EntityContex? I want to use the AspnetUsers table as my User table. Then in that case, AspnetUsers should have a lot of relationships with other tables in my General Context.

    • Edited by AlamBique Friday, November 24, 2017 5:41 PM
    Friday, November 24, 2017 4:52 PM
  • How can I join my GenralContext and my EntityContex? I want to use the AspnetUsers table as my User table.

    You can't join is the bottom line here you cant join the two contexts.

    I don't understand this.

    I'll assume that the MVC solution is allowing the user to logon to the application, and at that point, you know the user's credentials and you have the ability at that point to get the ID property from AspnetUsers for the logged-in user. 

    So, you should be able to take the ASPnetUsers ID and apply it  to any table where you are trying to crate some kind of relationship, a logical relationship, based on the known ID of the logged-on user with the ID for the user obtained from ASPnetUsers.

    • Marked as answer by AlamBique Friday, November 24, 2017 11:12 PM
    Friday, November 24, 2017 7:14 PM
  • Thank you very much DA924x. You are the first person to see the problem in this metodology I'm trying to do. I went through several forums and everyone was trying to solve ...

    And whenever I asked about it, I received many possible solutions. none worked. So the answer is that I can not do that.

    But then I was frustrated ... See 2 points that I imagined:
    1- I have a department table. And users should belong to 1 department. I can not put an AspNetUsers Id in departments, I should instead put a Departments id in AspNetUsers.
    2- I thought I could use to get the data from the related tables through the ApplicationUser. In other words, I make one:
    ApplicationUser = _UserManager.Users;

    And then I access...

    ApplicationUser.Departaments.Name.

    But if I undestend, the only way to do this is to replicate the general context by duplicating all User-related entities within the Identity contexto. I try this now.

    Thank you again
    Friday, November 24, 2017 11:11 PM
  • 1- I have a department table. And users should belong to 1 department. I can not put an AspNetUsers Id in departments, I should instead put a Departments id in AspNetUsers.

    Then you should have a Departmentlookup table that has ID and DepartmentName properties.

    You should have a DepartmentUser table that has an ID meaningless and only to satisfy EF, and it  will have a composite logical key of user-id from AspNetUsers and Department ID from Departmentlookup. In that way. you can have a user assigned to multiple departments.

    But if I undestend, the only way to do this is to replicate the general context by duplicating all User-related entities within the Identity contexto. I try this now.

    I don't think that is an optimal choice. I think you need to logically bring the two databases together as needed.

    Things that can help you is to stop all business and DB logic being used in the controllers.

    http://www.c-sharpcorner.com/UploadFile/56fb14/understanding-separation-of-concern-and-Asp-Net-mvc/

    Learn how to use the Repository pattern.

    https://msdn.microsoft.com/en-us/library/ff649690.aspx?f=255&MSPPError=-2147217396

    https://www.infragistics.com/community/blogs/dhananjay_kumar/archive/2016/03/07/how-to-implement-the-repository-pattern-in-asp-net-mvc-application.aspx

    Learn how to abstract a way from the underlying DB technology by using DTO pattern

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

     Learn how to use n-tier.

    https://msdn.microsoft.com/en-us/library/bb384398.aspx

    Understand SoC

    https://en.wikipedia.org/wiki/Separation_of_concerns

    Saturday, November 25, 2017 3:52 AM