How to autoCreateTables along with SimpleMembership tables in ASP.NET MVC - asp.net-mvc

Today, I created a new ASP.NET MVC 4 project - Internet application.
With all the files that comes in the solution in the Account Controller I saw an attribute called [InitializeSimpleMembership]
[Authorize]
[InitializeSimpleMembership]
public class AccountController : Controller
{}
and by only providing a proper db connectionstring property in the web.config
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.;
Initial Catalog=demo;
User ID=test;Password=test;" providerName="System.Data.SqlClient" />
and when the application runs, it checks if the available database exists or not and if not creates one and adds few memebership tables to it also. I must say I was very very impressed with the new MVC 4 - Internet app template.
Which brings me to my question :
I liked the idea of creating database and executing script from the application. I wanted to know how to add more tables to this.
For example : In the InitializeSimpleMembershipAttribute.cs file it check if a database is present, if not it creates it using the credentials present in the web.config and also adds the following tables to it.
UserProfile
webpages_Membership
webpages_OAuthMembership
webpages_Roles
webpages_UsersInRoles
what changes do I have to make to have my other tables to be added along with this ?
If this is possible, the idea of keeping sql scripts and executing them on each clean deploy can be avoided. I am working on a self-host MVC app ( It's Open-source, soon to come on Codeplex ;) ) so this will really be good for people who want to use my app without getting their hands dirty in SQL scripts.
Please can some one let me know if this is even possible. Thanks

There are two distinct parts to the tables being created:
The UserProfile table is created by adding the attribute [Table("UserProfile")] before the model in Models/AccountModels.cs (remember to add it as a DbSet to your context as well).
The 'webpages_' tables are created by the WebSecurity.InitializeDatabaseConnection call in Filters/InitializeSimpleMembershipAttribute.cs called by adding the [InitializeSimpleMembership] in Controllers/AccountController.cs. These are 'internal' tables required by the SimpleMembershipProvider and you would not typically want to alter them.
This is called the CodeFirst method of the EntityFramework (your other options are ModelFirst and DbFirst). To have your own POCOs/models auto created you would want to add the Table("TableName") attribute similar to UserProfile above.
Refer to the Entity Framework Website for full walkthroughs of the CodeFirst approach (and much much more).
http://msdn.microsoft.com/en-us/data/ef.aspx

Related

ASP.NET Identity 2.0 DB First Approach: Adding new Columns

I am trying to use ASP.NET Identity 2.0 with existing database.
I have created an MVC project (which uses Individual Account Authentication), then I registered for a use in order to create the DB.
Then:
I created scripts for the necessary tables and added them to my own DB
I added ADO.NET Entity Data Model (database first) which include my tables plus identity tables.
I ran the application and registered for a user, everything is going fine.
Now, I need to add a relation to AspNetUser table.
I added the Column LocationId with the relationship in DB.
I Added the following to the Application User Class:
public virtual Region Region { get; set; }
Then, I updated my Model and run the application, when I tried to register for new user, I got the following error:
AspNet UserLogin: EntityType: EntitySet 'AspNetUserLogins' is based on type 'AspNet UserLogin' that has no keys defined.
How is it possible to continue using DB First Approach in this scenario?
Identity uses Code First approach for making Identity System make customization as more as possible and you are using DB first approach for your common data access. So there are 2 contexts, one is for your data and other is for you Identity. You need to write Identity classes and make a code first migration of Identity context class by typing in the Package Manager Console as:
`Enable-Migrations -ContextNameType [Your_Identity_Context]
This will enable code first migrations just for your Identity context type. If you want to add region property in your user table, then in 'ApplicationUser' (or any class derived from IdentityUser) add the required region property and then apply the migrations to update the user table in the database.
Generating SQL script and applying to the database is not a good approach.

Automatically updating database with multiple DbContexts

I'm using EF6 in ASP.NET 5 project. Where I'm using ASP.NET Identity as the authentication mechanism. As anyone would do, I have modeled my domain objects in a separate dll project and for data access logic I have a separate project. This data project contains EF migrations, DbContext for domain models, repositories and Unit of work.
And I have a service layer which is contacted by ASP.NET controllers and this service layer will communicate with data layer and do required operations.
In the main ASP.NET web project I have the default DbContext which is related to Identity and it's migrations.
Having two DbContexts somehow prevents me from updating database automatically. If I had only one DbContext after I create migrations for model changes, it will automatically run on the first time I try to access the website. This doesn't happen anymore, always I have to run the "update-database" command manually.
One solution I have right now is to add a reference to "Microsoft.AspNet.Identity.EntityFramework" in my data project and use Identity context contain my domain tables. But adding an ASP.NET reference in my data project is something I don't want to do unless I have no other options. Because data layer is not even communicating directly with web layer.
Even though this video by Scott Allen discuss about this issue, a solution is not proposed.
You can kick in migrations explicitly by using database initializer and using MigrateDatabaseToLatestVersion. This initializer allows you explicitly state the context and configuration you want to use. Something like:
SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>());
You can also call all the logic manually, effectively doing the same as Update-Database cmdlet, when you want during app start. Look at DbMigrator class.
You can run migration inside each DbContext constructor separately.
public class DataContext: DbContext
{
static DaraContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DataContext, Configuration>());
}
}
public class ApplicationDbContext : IndetityDbContext
{
static ApplicationDbContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
}
}

How to inherit from IdentityUser in entity framework designer

I have an asp.net mvc project that uses asp.net Identity to authenticate users. The database has been designed in entity framework designer.
There is a table named "Farmers" and I want to allow each farmer to login to the application. As I know in order to achieve this, the farmer must inherit from IdentityUser, but how can I do this in entity framework designer?
what is your mvc version??
in mvc5 this is a good response
http://blogs.msdn.com/b/webdev/archive/2013/10/16/customizing-profile-information-in-asp-net-identity-in-vs-2013-templates.aspx
for this way u can mixed the two tables.
the other way is create an relationship between the two tables an use
User.Identity.Name or
User.Identity.GetHashCode
an use this to obtain the values of connected user
After a lot of hours of research I figured out that inherit from ApplicationUser or IdentityUser is not possible using the Entity Framework Designer.
My solution is to create a Code First Model from the existing database and then inherit from ApplicationUser.
As far as I know you can't really do that and I would argue that you shouldn't even try to do that even if you could.
By inheriting from IdentityUser you are saying that the Farmer can be described by properties like SecurityStamp, Roles or PasswordHash (inherited from IdentityUser) which does not make that much sense from a design point of view.
If what you are looking for is having a direct association between a user and a farmer you could simply add a required UserId property in you Farmer model. So whenever you create a new UserIdentity instance you also create a new Farmer instance as well with the UserId set to be the Id property of the newly created UserIdentity.

Identity 2.0. How to relate a user table in my EF context to Identity AspNetUsers table

I am using a boiler-plate VS2013 generated project (Code First, Migrations).
I wish to take the easy route and use all the built-in Identity API for handling of authentication and accounts (register, login all that).
Yet I wish to have a separate user table (let’s call it AppUser) with its own attributes that is not part of Identity because I am implementing my own domain with other relationships (Company => user hierarchy, Documents, etc) this is all admin’d outside of Identity by my custom pages. The AspNetUser would have already registered his account prior to my custom pages wiring him in.
My issue is how do I setup a relationship in the context from AppUser to AspNetUsers.
I thought this would be pretty simple but I am lost.
The only thing I can come up with is to have AppUser have a string called AspNetUser_ID that I would manually join to the AspNetUser table.
This seems pretty brittle and I would prefer it could have a FK constraint.
The other thing I cannot figure out is how to get AspNetUser in my DBContext so it is accessible.
Any help would be great.
Since you're using the boilerplate template, you should be able to find a class file named IdentityModels.cs in the Models folder. There, you can find the ApplicationUser class, to which you can add all the extra properties you want, as with any other Code First entity. This is the entity that maps to the AspNetUsers table. Here you could just add your AppUser class as a navigation property, or maybe, to keep things simple, add the properties from AppUser to ApplicationUser, so you only have one ***User entity to deal with.

Asp mvc 3 noobie: Why is the code-first method not building my DB on sql server?

I am an ASP MVC 3 noobie who has done a few tutorials. Now I'm trying to build a site. All of the tutorials on the microsoft website emphasize the code-first approach: you define your model with code and then create a datacontext and then the entity framework creates/manages the DB based on your code.
I set up an Employees class and a DataBaseContext class that inherits from DbContext. I added a connection string to Web.config connection string that successfully links DataBaseContext to an already existing empty DB on SQL server. EDIT= That was the problem. See my answer below
But when I try to run the Employees controller created thru scaffolding, I get this error
Invalid object name 'dbo.Employees'.
Description: An unhandled exception occurred during the execution of...
Exception Details: System.Data.SqlClient.SqlException: Invalid object name 'dbo.Employees'.
I followed this post SqlException (0x80131904): Invalid object name 'dbo.Categories' and realized that if I create an employees table on the DB, this excpetion goes away (I get a new one saying that the column names are invalid).
But I thought the whole point of MVC 3 is that the framework will make the DB for you based on the code.
Maybe I need a line of code in the Global.asax Application_start() to create the database? Here is my application_start method:
Sub Application_Start()
AreaRegistration.RegisterAllAreas()
RegisterGlobalFilters(GlobalFilters.Filters)
RegisterRoutes(RouteTable.Routes)
End Sub
Here is the code for Employee:
Public Class Employee
Property EmployeeID As Integer
Property First As String
Property Last As String
Property StartDate As DateTime
Property VacationHours As Integer
Property DateOfBirth As DateTime 'in case two employees have the same name
End Class
Here is the code for the DB context:
Imports System.Data.Entity
Public Class DatabaseContext
Inherits DbContext
Public Property Employee As DbSet(Of Employee)
Public Property AnnualLeave As DbSet(Of AnnualLeave)
End Class
What am I missing?
By default EF uses DropCreateDatabaseIfModelChanges<TContext> database initializer. Accordingly to the MSDN:
An implementation of IDatabaseInitializer<TContext> that will delete, recreate, and optionally re-seed the database with data only if the model has changed since the database was created. This is achieved by writing a hash of the store model to the database when it is created and then comparing that hash with one generated from the current model.
Since the database was created manually, EF can't find the hash and decides do not perform any further initialization logic.
You might want to look into this article, same question successfully answered already.
Or it can be this (also resolved successfully)
Answer to your problem is most likely one of the two.
Hope this will help you
Does the name you're specifying for your connection string match the name of your database context?
For example:
Context
var myDbContext = new MyDbContext();
Connection string
<connectionStrings>
<add name="MyDbContext" connectionString="YOUR.CONNECTION.STRING" providerName="System.Data.SqlServer" />
</connectionStrings>
Try and see if this post I wrote about DbContext with MVC works for you: Code-First
Not a lot to be done to get this to work, but there are a few things that are easily missed that will cause a bunch of head aches.
hope this helps
I had already created a database with that name on SQL server. Once I deleted the existing database, the code first framework created the tables for me like it was supposed to. It seems like if the database already exists, the framework won't set up the tables for you. It wants to create the whole DB from scratch.
You were using AdventureWorks Database?
It has it's own schema assigned to the employees table. HumanResources.Employees and not the default dbo.Employees.
Even though I've identified the problem, I don't know the solution to using the database as configured with the HumanResources schema.
Anybody know?

Resources