ASP.NET Identity Model First fails because of renamed AspNetUserRoles columns - entity-framework

Like several others I have tried to implement ASP.NET Identity Model First. Everything works fine once you have tried, errored, fumed, searched and resolved.. I thought.
See also:
ASP.NET Identity with EF Database First MVC5
http://danieleagle.com/blog/2014/05/setting-up-asp-net-identity-framework-2-0-with-database-first-vs2013-update-2-spa-template/
Course of action, summarized:
Created default project (MVC5)
Create database
Update connectionstring in the web.config
Run website, register: tables get created
Create EF Model (edmx)
Import Identity tables (everything fine up to this point)
Modified xxx.Context.tt to inherit from IdentityDbContext
Generate database script (trouble starts here)
I have solved the issues that appeared (up to the latest step). For completeness I will describe them.
Using the default Identity context
Everything works fine: tables get created, I can Register and login. This is however not the situation I want: I want to use a Model First approach.
Using the custom, model first context using the EF connectionstring
Modifying the CreatePerOwinContext so that it uses my Model First context:
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(CustomModelFirstDbContext.Create);
And the ApplicationUserManager so that it uses the Model First context:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<CustomModelFirstDbContext>()));
Results in:
Server Error in '/' Application.
The entity type ApplicationUser is not part of the model for the
current context.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The entity type
ApplicationUser is not part of the model for the current context.
Source Error:
An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of
the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: The entity type ApplicationUser is not
part of the model for the current context.]
Using the "normal" connectionstring with the custom, Model First context
An exception of type
'System.Data.Entity.Infrastructure.UnintentionalCodeFirstException'
occurred in WebApplication1.dll but was not handled in user code
Additional information: Code generated using the T4 templates for
Database First and Model First development may not work correctly if
used in Code First mode. To continue using Database First or Model
First ensure that the Entity Framework connection string is specified
in the config file of executing application. To use these classes,
that were generated from Database First or Model First, with Code
First add any additional configuration using attributes or the
DbModelBuilder API and then remove the code that throws this
exception.
So, I figured I needed the default Identity context to use Identity, and use the custom Model First context for everything else. Not the preferred solution, but acceptable.
Rolled everything back
Import Identity tables from database
(Optional) Created entities via the Model First approach
Generated database script
Both the normal project and a quick sanity check test project have the same problem with the AspNetUserRoles table. That is a junction table, and when importing it in the EF designer, everything is OK. You won't see it since it is a many to many relationship, and when inspecting the association between AspNetRole and AspNetUser it looks good.
Designer and mapping details:
However, when generating the sql script, EF modifies the keys.
Designer and mapping details:
Generated SQL script:
-- Creating table 'AspNetUserRoles'
CREATE TABLE [dbo].[AspNetUserRoles] (
[AspNetRoles_Id] nvarchar(128) NOT NULL,
[AspNetUsers_Id] nvarchar(128) NOT NULL
);
GO
In EF, you can't change the names of the mappings in the designer (thread on social.msdn.microsoft.com).
Subsequently the creation of a new user wil fail, using the originally created context because the junction table contains the wrong columns:
Server Error in '/' Application.
Invalid column name 'UserId'.
Invalid column name 'UserId'.
Invalid column name 'UserId'.
Invalid column name 'RoleId'.
Invalid column name 'UserId'.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.Data.SqlClient.SqlException: Invalid column name 'UserId'. Invalid column name 'UserId'. Invalid column name 'UserId'. Invalid column name 'RoleId'. Invalid column name 'UserId'.
Source Error:
Line 89: {
Line 90: var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
Line 91: IdentityResult result = await UserManager.CreateAsync(user, model.Password);
Line 92: if (result.Succeeded)
Line 93: {
What is the solution? Are there any alternatives than trying to change the generated script, or moving to Code First?

If you in the begginning and db is still empty than
I believe the easiest workaround is:
Create EF Model(edmx).
Right click on model "Generate Database from model".
It will create DDL file (snippet below)
Replace all wrong "AspNetUsers_Id" and "AspNetRoles_Id" for correct values.
Right click "execute".
Works for me.
-- Creating non-clustered index for FOREIGN KEY 'FK_AspNetUserRoles_AspNetUser'
CREATE INDEX [IX_FK_AspNetUserRoles_AspNetUser]
ON [dbo].[AspNetUserRoles]
([AspNetUsers_Id]); //replace for UserId
Happy coding!

Related

How can I map one custom Entity to some database tables in Entity Framework?

I have a database first model in my project. The 3 tables Document, DocumentItem and Product are imported from the database.
I want to create a new Entity named Order that joins some fields of these three database tables. I created that Entity as you see in the first picture and filled its table mapping as you see in the second picture.
After the build of the project I get the following errors:
Severity Code Description Project File Line Suppression State
Error Error 3025: Problem in mapping fragments starting at line 193:Must specify mapping for all key properties (Product.Id) of table Product. EFTest C:\Users\Me\documents\visual studio 2015\Projects\EFTest\EFTest\Data\EfTest.edmx 194
Error Error 3025: Problem in mapping fragments starting at line 186:Must specify mapping for all key properties (Document.Id) of table Document. EFTest C:\Users\Me\documents\visual studio 2015\Projects\EFTest\EFTest\Data\EfTest.edmx 187
Error Error 3024: Problem in mapping fragments starting at line 193:Must specify mapping for all key properties (Orders.Id) of the EntitySet Orders. EFTest C:\Users\Me\documents\visual studio 2015\Projects\EFTest\EFTest\Data\EfTest.edmx 194
Error Error 3024: Problem in mapping fragments starting at line 186:Must specify mapping for all key properties (Orders.Id) of the EntitySet Orders. EFTest C:\Users\Me\documents\visual studio 2015\Projects\EFTest\EFTest\Data\EfTest.edmx 187
I could not find the source of the problem. How can I solve these errors?
The error tells there's a foreign key missing in your project !
Considering that you know You cannot simply add tables from the database into your model and then create a new association in the model. By default it uses independent association which must be mapped to its database counterpart(e.g the relation must exists in the database as well). You must model your relation as FK association but it allows only one-to-one and one-to-many associations. In another words, when you add a new table with "Include foreign key columns in the model" checked in EF4 and the table doesn't contain any foreign key relationships then you try to add a association it will trigger this error. The solution is to Define Constraints in an EF4 model that don’t exist in the database.
Sometimes we have unwanted conflicts which can cause such this problems when you can delete the table from the EF designer and also delete everything related to that table manually (in the XML file), then add the table again and put the right mappings again.

Can't create migration to add new column to table: Invalid column name

I'm trying to add a column to an existing table. It is simply a string column, not involved in any kind of keys and this is the only change I'm trying to make. I am creating the migration with the powershell call
dotnet ef migrations add [migration name] --context [context name]
As I've done many times before. I get an error that says.
An error occurred while calling method 'BuildWebHost' on class 'Program'. Continuing without the application service provider. Error: Invalid column name '[column id]'.
Unable to create an object of type 'DashboardContext'. Add an implementation of 'IDesignTimeDbContextFactory<[context name]>' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.
Apparently this error means that the column doesn't exist, but that's precisely why I'm trying to create the migration - to add it.
EDIT: It turns out that adding the migration includes a call to Startup->Configure which in my case accessed that table. Any info on why that is the case would be appreciated. Meanwhile I got around it by commenting that code out while creating the migration.

Cannot add Postgresql view to EDMX File

I ensured my tables all have primary keys which are not null fields. I ensured my views contain one of these primary key fields. Nothing works.
When I try to add the views in the wizard, Visual Studio returns me to the EDMX diagram view but the views I just added are not there! This below shows when returned to the diagram view:
The model was generated with warnings or errors.PMCPolyModel.edmx Please see the Error List for more details. These issues must be fixed before running your application.
Loading metadata from the database took 00:00:00.5619194.
Generating the model took 00:00:00.5230463.
Added the connection string to the App.Config file."
The internal error is:
Error 6013: The table/view '[My View Name]' does not have a primary key defined and no valid primary key could be inferred. This table/view has been excluded. To use the entity, you will need to review your schema, add the correct keys, and uncomment it."
I closed and reopened Visual Studio and the EDMX diagram view states "The Entity Data Model Designer is unable to display the file you requested. You can edit the model using the XML Editor."

EF7 "Invalid Object Name 'xyz'" when manually scaffolding existing database

I've published a DB using an SqlDatabase Project.
I've manually created POCO classes, as well as a Db context to match the published database.
Whenever I try to execute an EF statement, valid SQL Query is generated, but I receive the error
An exception occurred in the database while iterating the results of a query.
System.Data.SqlClient.SqlException (0x80131904): Invalid object name '[xyz]'
The properties on the EF class match exactly type/nullable/name/etc in the database. The query generated, when run manually works fine.
Any help appreciated.

EF code-first migration: SqlCeException altering NTEXT column

My application uses Entity Framework 5.0 code-first on top of a Sql CE database. Until now, we have used Automatic Migrations to manage entity mapping changes. However, I now have a change for which I need to create a custom migration to ensure no data is lost during the update. I made my changes to the entities, and used the Add-Migration command which generated Up() and Down() methods for me. I customized the Up() method to insert my custom sql to preserve the data, and tested my application.
When I run the application, I received the error:
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.
Ok, I don't understand this because all of my changes are detailed in the Up() method that got executed.
So I turn Automatic Migrations back on just to see what happens. Now I receive this error:
"Cannot alter column of type NTEXT or IMAGE [ Column Name = LastName ]"
This error comes from a table/entity that hasn't even been touched with my changes. The existing database has this string mapped to nvarchar(4000). If I examine the DB after I receive this exception, I observe that the columns have been changed to ntext. What is EF doing? Why is it touching tables that haven't been changed? How can I get more information on what is going on here?
Update:
As a workaround, I attempted to mark each and every string type in my entities with a data annotation as such:
[Column(TypeName = "ntext")]
public virtual string LastName
{
get;
set;
}
Now all of my strings are using ntext in the database. This leads to further exceptions when queries are performed:
The ntext and image data types cannot be used in WHERE, HAVING, GROUP BY, ON, or IN clauses, except when these data types are used with the LIKE or IS NULL predicates.
So, to summarize:
Turning off automatic migrations causes EF to detect phantom changes and throw exceptions
Turning on automatic migration in conjunction with a custom migration causes all existing strings to be mapped to ntext
strings mapped to ntext cannot be queried, effectively making them useless in my application
For me, a modification of an Up method worked out.
SerialNumber = c.String(maxLength: 99)
was applied instead of
SerialNumber = c.String()
i had the same issue and i fixed by editing the table column data type manually by opening SQl Server Compact/SQlite Toolbox explorer windows, and then expend the database name, then expend the table you want to edit and right click the column you want to edit, and click drop script, then run the scrip and the column will be dropped from the table, then right click the table and click add column and from here you can choose what data type you want and add the new column that way. I hope this helps some one.