Reputation: 8711
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
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
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:
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
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
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