Entity Framework Code-First Issues (SimpleMembership UserProfile table)

asp.net-mvc-4 c# entity-framework

Question

If you've used ASP.NET MVC 4, you'll note that the SimpleMembership provider is utilized by default for an Internet Application. This is acceptable and effective.

They have a POCO for the default database creation, which is where the problem lies.UserProfile defined as follows:

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
}

It is then produced as follows:

using (var context = new UsersContext())
{
    if (!context.Database.Exists())
    {
         // Create the SimpleMembership database without Entity Framework migration schema
         ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
    }
}

The database is produced perfectly and operates without a hitch in this case. However, if I were to erase the database and update the POCO in this manner:

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string EmailAddress { get; set; }

    public string FirstName { get; set; }
    public string Surname { get; set; }

    public string Country { get; set; }

    public string CompanyName { get; set; }
}

The first 2 columns are the only ones created.UserId and EmailAddress . Code-wise, it's perfect (talking about login/registration), but clearly no further user information is saved.

Am I overlooking something here? It must create the database based on the wholeUserProfile object.

1
28
9/19/2012 8:01:15 PM

Accepted Answer

It seems that I now grasp this, and that everything was likely simply a big mistake.

As it turned out, I had anticipated((IObjectContextAdapter)context).ObjectContext.CreateDatabase(); to do tasks that it plainly lacks, such as creating all of the database's blank tables or, if they already exist but are different, just updating them.

As a matter of fact, it truly runs aCREATE DATABASE statement, which is the most pointless thing I have ever heard. Since a database is always there unless you're working in a really bizarre context (in which case, no tables would ever be created! ), I'd prefer not provide real-world users access to construct databases.

Anyway, I was able to resolve my particular problem viaUserProfile (as well as associated tables) to build the database using theDropCreateDatabaseIfModelChanges force an initialization in the manner described below:

public SimpleMembershipInitializer()
{
#if DEBUG
    Database.SetInitializer<DataContext>(new DropCreateDatabaseIfModelChanges<DataContext>());
#else
    Database.SetInitializer<DataContext>(null);
#endif

    try
    {
        using (var context = new DataContext())
        {
            if (!context.Database.Exists())
            {
                ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
            }
            context.Database.Initialize(true);
        }

        WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true);
    }
    catch (Exception ex)
    {
        throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
    }
}

This is effective and ideal for development, but it is mostly worthless in real-world situations since it will essentially dump the database and start over from scratch if the model changes. I believe that this renders the whole code-first methodology almost worthless in its basic form, and I will likely end up switching back to a from-DB edmx generation.

The "mystery" underlyingUserProfile Is the table still being created?WebSecurity.InitializeDatabaseConnection will, depending on the information you put into it, initialize the table if it doesn't already exist.EmailAddress was developed in place ofUserName because I altered it for this.

5
9/23/2012 10:47:51 PM

Popular Answer

1 - Migrations must be enabled, preferably using EntityFramework. 5. UseEnable-Migrations in the package manager NuGet.

Move your mouth.

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true); 

in your YourMvcApp/Migrations/Configuration.cs class's Seed method

    protected override void Seed(UsersContext context)
    {
        WebSecurity.InitializeDatabaseConnection(
            "DefaultConnection",
            "UserProfile",
            "UserId",
            "UserName", autoCreateTables: true);

        if (!Roles.RoleExists("Administrator"))
            Roles.CreateRole("Administrator");

        if (!WebSecurity.UserExists("lelong37"))
            WebSecurity.CreateUserAndAccount(
                "lelong37",
                "password",
                new {Mobile = "+19725000000", IsSmsVerified = false});

        if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
            Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"});
    }

After EF5 has finished building your UserProfile table, contact WebSecurity to activate it. SimpleMembershipProvider is only registered with the already-existing UserProfile table when InitializeDatabaseConnection is used to inform SimpleMembershipProvider of the UserId and UserName columns. I'm also providing an illustration of how you may include Users, Roles, and link the three in your Seed method using unique UserProfile characteristics and fields, such as a user's mobile number (number).

3 - EF5 will now provide your table with all of your customized settings when you execute update-database from the Package Manager Console.

Please refer to this article with the sourcecode: http://blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom-user-properties/ for further references.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow