MVC - Additional ApplicationUser properties not getting added to AspNetUsers - asp.net-mvc

I created a new project that is using MVC Entity Framework with Individual User Accounts. I want to add FirstName and LastName as properties of a user. The steps in this blog amount to these:
1) Create and run new Project
2) Enable Migrations
3) Add new Properties to ApplicationUser in IdentityModel
4) Add Migration and Update Database
- after this you can verify the new fields are in AspNetUsers table
5) Update RegisterViewModel
6) Update Register View
7) Update Account Controller's Register Post
I did steps 1 - 4, but when I look at AspNetUsers table the fields are not there and I don't understand why.
This is what I did per step 3:
Public Class ApplicationUser
Inherits IdentityUser
Public FirstName As String
Public LastName As String
But after step 4 this is what my table looks like:
Why are FirstName and LastName not getting added to the table as expected?
This is what is in my Package Manager Console:
PM> enable-migrations
Checking if the context targets an existing database...
Code First Migrations enabled for project CustomUserProperties.
PM> add-migration "name"
Scaffolding migration 'name'.
The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running 'Add-Migration name' again.
PM> update-database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Applying explicit migrations: [201510191912542_name].
Applying explicit migration: 201510191912542_name.
Running Seed method.
PM>
This is the contents of the Migration:
Imports System
Imports System.Data.Entity.Migrations
Imports Microsoft.VisualBasic
Namespace Migrations
Public Partial Class name
Inherits DbMigration
Public Overrides Sub Up()
CreateTable(
"dbo.AspNetRoles",
Function(c) New With
{
.Id = c.String(nullable := False, maxLength := 128),
.Name = c.String(nullable := False, maxLength := 256)
}) _
.PrimaryKey(Function(t) t.Id) _
.Index(Function(t) t.Name, unique := True, name := "RoleNameIndex")
CreateTable(
"dbo.AspNetUserRoles",
Function(c) New With
{
.UserId = c.String(nullable := False, maxLength := 128),
.RoleId = c.String(nullable := False, maxLength := 128)
}) _
.PrimaryKey(Function(t) New With { t.UserId, t.RoleId }) _
.ForeignKey("dbo.AspNetRoles", Function(t) t.RoleId, cascadeDelete := True) _
.ForeignKey("dbo.AspNetUsers", Function(t) t.UserId, cascadeDelete := True) _
.Index(Function(t) t.UserId) _
.Index(Function(t) t.RoleId)
CreateTable(
"dbo.AspNetUsers",
Function(c) New With
{
.Id = c.String(nullable := False, maxLength := 128),
.Email = c.String(maxLength := 256),
.EmailConfirmed = c.Boolean(nullable := False),
.PasswordHash = c.String(),
.SecurityStamp = c.String(),
.PhoneNumber = c.String(),
.PhoneNumberConfirmed = c.Boolean(nullable := False),
.TwoFactorEnabled = c.Boolean(nullable := False),
.LockoutEndDateUtc = c.DateTime(),
.LockoutEnabled = c.Boolean(nullable := False),
.AccessFailedCount = c.Int(nullable := False),
.UserName = c.String(nullable := False, maxLength := 256)
}) _
.PrimaryKey(Function(t) t.Id) _
.Index(Function(t) t.UserName, unique := True, name := "UserNameIndex")
CreateTable(
"dbo.AspNetUserClaims",
Function(c) New With
{
.Id = c.Int(nullable := False, identity := True),
.UserId = c.String(nullable := False, maxLength := 128),
.ClaimType = c.String(),
.ClaimValue = c.String()
}) _
.PrimaryKey(Function(t) t.Id) _
.ForeignKey("dbo.AspNetUsers", Function(t) t.UserId, cascadeDelete := True) _
.Index(Function(t) t.UserId)
CreateTable(
"dbo.AspNetUserLogins",
Function(c) New With
{
.LoginProvider = c.String(nullable := False, maxLength := 128),
.ProviderKey = c.String(nullable := False, maxLength := 128),
.UserId = c.String(nullable := False, maxLength := 128)
}) _
.PrimaryKey(Function(t) New With { t.LoginProvider, t.ProviderKey, t.UserId }) _
.ForeignKey("dbo.AspNetUsers", Function(t) t.UserId, cascadeDelete := True) _
.Index(Function(t) t.UserId)
End Sub
Public Overrides Sub Down()
DropForeignKey("dbo.AspNetUserRoles", "UserId", "dbo.AspNetUsers")
DropForeignKey("dbo.AspNetUserLogins", "UserId", "dbo.AspNetUsers")
DropForeignKey("dbo.AspNetUserClaims", "UserId", "dbo.AspNetUsers")
DropForeignKey("dbo.AspNetUserRoles", "RoleId", "dbo.AspNetRoles")
DropIndex("dbo.AspNetUserLogins", New String() { "UserId" })
DropIndex("dbo.AspNetUserClaims", New String() { "UserId" })
DropIndex("dbo.AspNetUsers", "UserNameIndex")
DropIndex("dbo.AspNetUserRoles", New String() { "RoleId" })
DropIndex("dbo.AspNetUserRoles", New String() { "UserId" })
DropIndex("dbo.AspNetRoles", "RoleNameIndex")
DropTable("dbo.AspNetUserLogins")
DropTable("dbo.AspNetUserClaims")
DropTable("dbo.AspNetUsers")
DropTable("dbo.AspNetUserRoles")
DropTable("dbo.AspNetRoles")
End Sub
End Class
End Namespace
FirstName and LastName are not in "With" for the AspNetUsers table.
UPDATE:
I restarted again from scratch, and this time what I did was create the Migration, then manually added FirstName and LastName in the AspNetUsers Up function, then ran update-database. That actually worked.
So why it didn't automatically add those fields to the migration, I don't know. But if I do that manually it seems like it works that way.
Thank you!

See the answer I posted in this questions I posted subsequent to this one.
With that I am able to include additional user properties and it all works!
Whether or not that is the "best" way to do it may be another question, but since it's essentially the same as what MVC provides initially I don't see any issues with it.

Related

ASP.net MVC 5 EF6 Error While updating the database

I am quite new to Asp.net MVC 5 EF6. I am developing the application for Contoso Unversity which is provided by Microsoft on asp.net website. In chapter no.11 Implementing the Inheritance after adding the inheritance and adding the migration through migration command it worked but when i tried to apply the update-database command to the PMC, I faced this error:
Error Number:15248,State:1,Class:11 Either the parameter #objname is
ambiguous or the claimed #objtype (OBJECT) is wrong.
This is the code of My /inheritance migration class.
please guide me to a fix.
namespace ContosoUniversity.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Inheritance : DbMigration
{
public override void Up()
{
// Drop foreign keys and indexes that point to tables we're going to drop.
DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student");
DropIndex("dbo.Enrollment", new[] { "StudentID" });
RenameTable(name: "dbo.Instructor", newName: "Person");
AddColumn("dbo.Person", "EnrollmentDate", c => c.DateTime());
AddColumn("dbo.Person", "Discriminator", c => c.String(nullable: false, maxLength: 128, defaultValue: "Instructor"));
AlterColumn("dbo.Person", "HireDate", c => c.DateTime());
AddColumn("dbo.Person", "OldId", c => c.Int(nullable: true));
// Copy existing Student data into new Person table.
Sql("INSERT INTO dbo.Person (LastName, FirstName, HireDate, EnrollmentDate, Discriminator, OldId) SELECT LastName, FirstName, null AS HireDate, EnrollmentDate, 'Student' AS Discriminator, ID AS OldId FROM dbo.Student");
// Fix up existing relationships to match new PK's.
Sql("UPDATE dbo.Enrollment SET StudentId = (SELECT ID FROM dbo.Person WHERE OldId = Enrollment.StudentId AND Discriminator = 'Student')");
// Remove temporary key
DropColumn("dbo.Person", "OldId");
DropTable("dbo.Student");
// Re-create foreign keys and indexes pointing to new table.
AddForeignKey("dbo.Enrollment", "StudentID", "dbo.Person", "ID", cascadeDelete: true);
CreateIndex("dbo.Enrollment", "StudentID");
}
public override void Down()
{
CreateTable(
"dbo.Student",
c => new
{
ID = c.Int(nullable: false, identity: true),
LastName = c.String(nullable: false, maxLength: 20),
FirstName = c.String(nullable: false, maxLength: 20),
EnrollmentDate = c.DateTime(nullable: false),
})
.PrimaryKey(t => t.ID);
AlterColumn("dbo.Person", "HireDate", c => c.DateTime(nullable: false));
DropColumn("dbo.Person", "Discriminator");
DropColumn("dbo.Person", "EnrollmentDate");
RenameTable(name: "dbo.Person", newName: "Instructor");
}
}
}
Consider:
1. Deleting all Migration files in your Migrations folder
2. Renaming your database in the connection string
3. Running PM> add-migration
4. Running PM> update-database

MVC Application using old DBContext

I went through the Movies tutorial on asp.net, which went fine. Created the application using a local SQL Server instance, database was created flawlessly, and all functionality worked as designed. I created a new, entirely separate application without importing or copying anything from the Movies application. Defined a new model and DBContext, new controller, etc. When I try to execute the application for the same time I get the following error:
The model backing the 'OnlineAppDBContext' context has changed since the >database was created. Consider using Code First Migrations to update the >database (http://go.microsoft.com/fwlink/?LinkId=238269).
I went through the exercise of adding the migrations and noticed in the init migration I added that it is referencing the Movie model and database:
public override void Up()
{
CreateTable(
"dbo.OnlineApps",
c => new
{
ID = c.Int(nullable: false, identity: true),
FirstName = c.String(),
MiddleInitial = c.String(),
LastName = c.String(),
PreviousFullName = c.String(),
Gender = c.String(),
BirthDate = c.DateTime(nullable: false),
SSN = c.String(),
Tobacco = c.Boolean(nullable: false),
Address1 = c.String(),
Address2 = c.String(),
City = c.String(),
County = c.String(),
State = c.String(),
ZipCode = c.String(),
HomePhone = c.String(),
WorkPhone = c.String(),
CellPhone = c.String(),
Email = c.String(),
PCPChoice = c.String(),
})
.PrimaryKey(t => t.ID);
DropTable("dbo.Movies");
}
public override void Down()
{
CreateTable(
"dbo.Movies",
c => new
{
ID = c.Int(nullable: false, identity: true),
Title = c.String(maxLength: 60),
ReleaseDate = c.DateTime(nullable: false),
Genre = c.String(nullable: false, maxLength: 30),
Price = c.Decimal(nullable: false, precision: 18, scale: 2),
Rating = c.String(maxLength: 5),
})
.PrimaryKey(t => t.ID);
DropTable("dbo.OnlineApps");
}
The Up() method looks to do the correct table structure for my new model, but then tries to drop dbo.Movies. The Down() method table structure is based on the Movie model, but I have no idea how it is aware of that, and then tries to drop the dbo.OnlineApps table.
I searched through all files in the new application and just for fun rebooted the entire machine, but still having the same problem. Any ideas?
EDIT On a hunch I created a new database on my server. The movies application used a database called 'Sandbox'. I created an 'OnlineApplication' database on the same server, changed the connection string in the new application, and when it ran the objects were created without error. While this got me through the issue I'm not overly satisfied with the answer. Why would the connection string convey any relation to a model from a completely different application? Is this stored somewhere it can be edited/deleted? Can I not define multiple contexts to the same database?

Define a field as autoincrement in EF5 migration

I'm creating a table using a EF migration such as:
this.CreateTable("Message",
c => new
{
Id = c.Long(nullable: false, identity: true, defaultValue: 0),
Subject = c.String(nullable: false, maxLength: 64),
Body = c.String(nullable: false, isMaxLength: true)
})
.PrimaryKey(c => c.Id)
.Index(c => c.Id, unique: true);
How can I define the Id field to be auto_increment? I'm pretty sure it has to be possible, but im just struggling to find out...
Thanks.
Ok, it seems that setting the property "identity: true" in field should be enough but for some reason the field is not defined as IDENTITY(1, 1).
Found a workaround in this post:
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/33db16ac-e166-455f-a47b-1e5fe0557979/
And it worked for me like this:
Id = new ColumnModel(PrimitiveTypeKind.Int64) { IsNullable = false, IsIdentity = true },
Now its defining the column as IDENTITY(1, 1)
If you do want to automatically generate it in code, you could skip the annotation on the Id field and do something like below.
public abstract class AbstractContext : DbContext {
/// <summary>
/// Custom processing when saving entities in changetracker
/// </summary>
/// <returns></returns>
public override int SaveChanges()
{
// recommended to explicitly set New Guid for appropriate entities
foreach (var entry in ChangeTracker.Entries<ModelBase>().Where(e => e.State == EntityState.Added) ) {
// only generate if property isn't identity...
Type t = entry.Entity.GetType();
var info = t.GetProperty("Id").GetCustomAttributes(
typeof(DatabaseGeneratedAttribute), true).Cast<DatabaseGeneratedAttribute>().Single();
if (info.DatabaseGeneratedOption != DatabaseGeneratedOption.Identity) {
entry.Entity.Id = Guid.NewGuid(); // now we make it
}
}
return base.SaveChanges();
}
}
For more information check Working with Entity Keys
I got this from the link Which I showed above comment.
I hope this will help to you.

Vaadin Container.Filter using variable number of criterias

Just implemented the new Container.Filter using this code:
Filter f =
new Or(new SimpleStringFilter(Columns.SEARCH.id(), "rpm-diastolic", true, false),
new Or(new SimpleStringFilter(Columns.SEARCH.id(), "rpm-systolic", true, false)),
new Or(new SimpleStringFilter(Columns.SEARCH.id(), "rpm-weight", true, false))) ;
container.addContainerFilter(f);
and works fine.
Now I would like to use the following in order to build as many criterias I would need by building dynamically the filter:
List<String> filters;
for(String filter : filters) {
Filter f = new Or(new SimpleStringFilter(Columns.SEARCH.id(), filter, true, false) );
container.addContainerFilter(f);
}
How can I do this for this code doesn't work...
OK,
I was able to do this by simply passing an array to the Or constructor this way:
Filter[] filtersToAdd = new Filter[filters.size()];
for(String filterString : filters) {
filtersToAdd[i++] =
new Or(new SimpleStringFilter(Columns.SEARCH.id(), filterString, true, false));
}
Filter f = new Or(filtersToAdd);
container.addContainerFilter(f);

ASP.NET MVC Webgrid Efficient Paging

I have a ASP.NET MVC 4 project and a SQL View (vvItem).
ItemController
MVCAppEntities db = new MVCAppEntities();
public ActionResult Index()
{
var itemqry = db.vvItem.OrderBy(s => s.name);
//var pageditems = itemqry.Skip(10).Take(20); // 25 seconds
return View(itemqry.ToList()); // 88 seconds
}
Index.cshtml View
#model IEnumerable<MVCApplication1.Models.vvItem>
#{
var norows = 20;
var grid = new WebGrid(Model, canPage: true, rowsPerPage: norows);
grid.Pager(WebGridPagerModes.NextPrevious);
#grid.GetHtml(tableStyle: "table", headerStyle: "header", columns: grid.Columns(
grid.Column(columnName: "name", header: "Name", canSort: true),
grid.Column(columnName: "quantity", header: "Quantity", canSort: true),
grid.Column(columnName: "code", header: "Code", canSort: true),
grid.Column(columnName: "Price", header: "Price", canSort: true),
))}
In vvItem I have almost 400000 records. I thought that the webgrid Pager would load (Take()) only the displayed records and it would know to Skip() the first records if I would go to the next pages.
Q : How can I efficiently make a view to load only the displayed records ?
I found 2 solutions : JSON version and NerdDinner
I'm not so good at JSON so I tried the NerdDinner solution. And as in my commented line
//var pageditems = itemqry.Skip(10).Take(20); itemqry is already loaded with all the records and it took a lot of time to load.
Q2 : How can I do paging now ? I need to modify the page no. from the Index method.
public ActionResult Index(int? page, string filter1 = " ", string filter2 = " ")
I made a SQL Stored Procedure
CREATE PROCEDURE SkipTake
#pagNo int,
#pageSize int
AS
select *
from (select *, row_number() over (order by COD) as rn
from vvSTOC
) as T
where T.rn between (#pagNo - 1) * #pageSize + 1 and #pagNo * #pageSize
I've added this sp in my EF model at Function Import so that it returns an entity (vvSTOC)
public ActionResult Index(int? page)
{
const int pageSize = 20;
return View(db.spSkipTake(page, pageSize).ToList());
}
It shouldn't execute the query right away as long as itemqry is an IEnumerable or IQueryable type. Can you cast it as an IQueryable as follows?
public ActionResult Index()
{
IQueryable<vvItem> itemQry = db.vvItem;
return View(itemQry.OrderBy(s => s.name).Skip(10).Take(20).ToList());
}
If the itemqry is the correct type it won't get executed until the .ToList() is called which converts it to an IList type. Check the SQL that is being produced to be sure.
public ActionResult Index(int? pageIndex)
{
int pageSize = 20;
var itemIndex = ((pageIndex??1) -1) * pageSize;
return View(db.vvItem.OrderBy(s => s.name).Skip(itemIndex).Take(pageSize).ToList());
}
Thanks for this.
I tweaked this to work with some input parameters in my SP to control the PageSize, PageNumber, SortIndex and SortOrder:
declare #sql nvarchar(1000) = '
select * from
(
select *, row_number() over(order by '+#SortIndex+' '+#SortOrder+') as RowNumber from #Results
) as T
where T.RowNumber between ('+#PageNumber+' - 1) * '+#PageSize+' + 1 and '+#PageNumber+' * '+#PageSize
exec sp_executesql #sql

Resources