实体框架代码优先问题(SimpleMembership UserProfile表)

Rud*_*ser 28 c# entity-framework asp.net-mvc-4

如果您使用过ASP.NET MVC 4,您会注意到Internet应用程序的默认设置是使用SimpleMembership提供程序,这一切都很好,并且工作正常.

问题是默认的数据库生成,他们有一个UserProfile像这样定义的POCO :

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

..然后生成如下:

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

这工作正常,数据库生成正常,工作没有问题.但是,如果我要像这样更改POCO并删除数据库:

[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; }
}
Run Code Online (Sandbox Code Playgroud)

仅生成前2列,UserId并且EmailAddress.它工作得很好(代码登录/注册),但显然没有存储我的其他用户数据.

我在这里错过了什么吗?当然它应该基于整个UserProfile对象生成数据库.

LeL*_*g37 47

1 - 您需要启用迁移,尤其是使用EntityFramework 5. Enable-Migrations在NuGet包管理器中使用.

2 - 移动你的

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true); 
Run Code Online (Sandbox Code Playgroud)

您的YourMvcApp/Migrations/Configuration.cs类中的Seed方法

    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"});
    }
Run Code Online (Sandbox Code Playgroud)

现在EF5将负责创建您的UserProfile表,在这样做之后,您将调用WebSecurity.InitializeDatabaseConnection仅使用已创建的UserProfile表注册SimpleMembershipProvider,同时调用SimpleMembershipProvider哪个列是UserId和UserName.我还展示了一个示例,说明如何添加用户,角色并将Seed方法中的两者与自定义UserProfile属性/字段相关联,例如用户的Mobile(数字).

3 - 现在,当您从Package Manager控制台运行update-database时,EF5将为您的表配置所有自定义属性

有关其他参考资料,请参阅本文的源代码:http: //blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom -user的属性/

  • rufo,你需要确保使用SimpleRoleProvider使用RoleProvider配置Web.confi,请参阅你需要的Web.Config条目的答案帖子中的链接. (2认同)

Rud*_*ser 5

看来我可能终于得到了这个,它可能只是一个巨大的误解.

事实证明,我期望((IObjectContextAdapter)context).ObjectContext.CreateDatabase();做到它根本不做的事情,即创建数据库中不存在的所有表,或者只是更新它们,如果它们存在并且它们不同.

实际发生的是它实际上是一个CREATE DATABASE声明,对我来说这是迄今为止最无用的事情.除非你在一个非常奇怪的环境中工作,否则你将永远拥有一个关闭的数据库,因此它将永远存在(随后表创建永远不会发生!),我宁愿不给现实世界的用户访问无论如何要创建一个数据库.

无论如何,我UserProfile通过使用DropCreateDatabaseIfModelChanges初始化程序解决了我想要(和相关表)创建数据库的特定问题,并强制进行如下初始化:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

..这是有效的,非常适合开发,但在实践中相当无用,因为如果模型发生变化,它将从字面上删除数据库并从头开始重新创建它.对我来说,这使得整个代码优先实践在它的默认形式中几乎无用,我可能最终会恢复到来自DB的edmx生成.

UserProfile仍然正在创建的表背后的"神秘" 是,WebSecurity.InitializeDatabaseConnection如果基于您传入其中的字段不存在,将初始化表,这就是为什么EmailAddress创建而不是UserName,因为我在此更改了它.