Rob Bowman
Rob Bowman

Reputation: 8711

EF 6 - Invalid column name 'Discriminator', two DbContexts

I have an MVC 5 app. I would like to use the standard aspnet.identity provider to enable user login through the standard \Account views. However, I also need to connect to a third-party database and want to use EF code-first for this too.

The context for my main database I took from a Scott Allen Pluralsight. I don't know why or what the "ApplicationUser" class is doing inheriting from the IdentityUser but it worked in his video and with a previous website I created. It looks as follows:

namespace ESBAMPortal.DataLayer
{
    // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
    public class ApplicationUser : IdentityUser
    {
    }

    class PortalContext : IdentityDbContext<ApplicationUser>, ESBAMPortal.DataLayer.IPortalContext
    {
        public PortalContext()
            : base("ESBamPortalConString")
        {
            this.Configuration.LazyLoadingEnabled = false;
        }

        public virtual DbSet<DomainClasses.Portal> Portal {get; set;}
    }
}

The context for the third-party database is as follows:

namespace ESBAMPortal.DataLayer
{

    public class ESBContext : DbContext, ESBAMPortal.DataLayer.IESBContext
    {
        public ESBContext()
            : base("ESBExceptionConString")
        {
            this.Configuration.LazyLoadingEnabled = false;
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }

        public virtual DbSet<ActionType> ActionTypes { get; set; }
        public virtual DbSet<Alert> Alerts { get; set; }
        public virtual DbSet<AlertCondition> AlertConditions { get; set; }
        public virtual DbSet<AlertEmail> AlertEmails { get; set; }
        public virtual DbSet<AlertHistory> AlertHistories { get; set; }
        public virtual DbSet<AlertSubscription> AlertSubscriptions { get; set; }
        public virtual DbSet<AlertSubscriptionHistory> AlertSubscriptionHistories { get; set; }
        public virtual DbSet<AuditLog> AuditLogs { get; set; }
        public virtual DbSet<AuditLogMessageData> AuditLogMessageDatas { get; set; }
        public virtual DbSet<Batch> Batches { get; set; }
        public virtual DbSet<Configuration> Configurations { get; set; }
        public virtual DbSet<ContextProperty> ContextProperties { get; set; }
        public virtual DbSet<Fault> Faults { get; set; }
        public virtual DbSet<Message> Messages { get; set; }
        public virtual DbSet<MessageData> MessageDatas { get; set; }
        public virtual DbSet<ProcessedFault> ProcessedFaults { get; set; }
        public virtual DbSet<UserSetting> UserSettings { get; set; }
    }
}

When I run the website I am able to pull data from the third-party website ok. However, when I try to login I receive the message:

Invalid column name 'Discriminator'

This is thrown as a result of making the call:

var user = await UserManager.FindAsync(model.UserName, model.Password);

Running EF Profiler I can see that it's attempting to execute the following SQL:

SELECT [Limit1].[C1]            AS [C1],
       [Limit1].[Id]            AS [Id],
       [Limit1].[UserName]      AS [UserName],
       [Limit1].[PasswordHash]  AS [PasswordHash],
       [Limit1].[SecurityStamp] AS [SecurityStamp]
FROM   (SELECT TOP (1) [Extent1].[Id]            AS [Id],
                       [Extent1].[UserName]      AS [UserName],
                       [Extent1].[PasswordHash]  AS [PasswordHash],
                       [Extent1].[SecurityStamp] AS [SecurityStamp],
                       '0X0X'                    AS [C1]
        FROM   [dbo].[AspNetUsers] AS [Extent1]
        WHERE  ([Extent1].[Discriminator] = N'ApplicationUser')
               AND ((((UPPER([Extent1].[UserName])) = (UPPER('rob' /* @p__linq__0 */)))
                     AND (NOT ((UPPER([Extent1].[UserName]) IS NULL)
                                OR (UPPER('rob' /* @p__linq__0 */) IS NULL))))
                     OR ((UPPER([Extent1].[UserName]) IS NULL)
                         AND (UPPER('rob' /* @p__linq__0 */) IS NULL)))) AS [Limit1]

Problem is, the AspNetUsersTable has no discriminator column.

Could anyone please explain where I've gone wrong and how I should fix?

Upvotes: 4

Views: 14704

Answers (4)

Abdullah Tahan
Abdullah Tahan

Reputation: 2129

This happen for me when i was adding two classes inherited from IdentityDbContext if so add Discriminator to AspNetRoles

AddColumn("dbo.AspNetRoles", "Discriminator", c => c.String(nullable: false, maxLength: 128));

Upvotes: 1

Rob Bowman
Rob Bowman

Reputation: 8711

I went back to basics, created a new MVC 5 app then generated a db migrations by running the following from the package manager console:

  • enable-migrations
  • add-migration 'first

When I inspected the code that was generated I could see that it included a "Discriminator" column in the AspNetUsers table. I went back to my "real" solution and compared, the 'first' migration code from my separate DataAccess project. This code didn't have a "Discriminator" column, I also noticed that it had additional columns such as "PhoneNumber" and "TwoFactorEnabled". This made me think that perhaps the MVC5 template was using a previous version of "Microsoft.AspNet.Identity.EntityFramework" - this turned out the be the case.

To resolve I went to the Manage Nuget Packages dialog of the MVC5 web app, uninstalled "Microsoft.AspNet.Identity.EntityFramework"(v1.0) then re-installed (v2.0). Subsequently when I ran login from the website it no tried to find a "discriminator" column and everything worked great.

I guess this has taught me a valuable lesson to pay more attention to the versions on Nuget packages that are used by VS Templates

Upvotes: 8

Omar.Alani
Omar.Alani

Reputation: 4130

because the ASP.NET MVC project has a "ApplicationUser" class that already overrides IdentityUser it adds the Discriminator column to the entity framework for you automatically. Try to drop the data base and rerun. again.

Check this http://forums.asp.net/t/1970682.aspx?ASP+NET+Identity+V2+Discriminator+Column

Upvotes: 1

Omar.Alani
Omar.Alani

Reputation: 4130

Try to drop the data base and rerun. again

Check this question 1. http://forums.asp.net/t/1970682.aspx?ASP+NET+Identity+V2+Discriminator+Column.http://

Also check this blogs.msdn.com/b/webdev/archive/2013/10/16/customizing-profile-information-in-asp-net-identity-in-vs-2013-templates.aspx

Upvotes: 0

Related Questions