C# 实体框架代码第一个问题(SimpleMembership UserProfile表)

C# 实体框架代码第一个问题(SimpleMembership UserProfile表),c#,entity-framework,asp.net-mvc-4,C#,Entity Framework,Asp.net Mvc 4,如果您使用过ASP.NET MVC 4,您会注意到Internet应用程序的默认设置是使用SimpleMembership提供程序,这一切都很好,而且工作正常 该问题与默认数据库生成有关,它们有一个用于UserProfile的POCO,定义如下: [Table("UserProfile")] public class UserProfile { [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]

如果您使用过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; }
}
。。然后生成如下所示:

using (var context = new UsersContext())
{
    if (!context.Database.Exists())
    {
         // Create the SimpleMembership database without Entity Framework migration schema
         ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
    }
}
这很好,数据库生成很好,没有问题。但是,如果我要像这样更改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; }
}
只生成前两列,
UserId
EmailAddress
。它在代码方面工作得很好(谈论登录/注册),但显然没有存储我的其他用户数据


我是不是遗漏了什么?当然,它应该根据整个
UserProfile
对象生成数据库。

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

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

实际上,它实际上运行了一个
createdatabase
语句,这对我来说是有史以来最无用的东西。除非您在一个非常奇怪的环境中工作,否则数据库总是处于关闭状态,因此它总是存在的(随后表的创建将永远不会发生!),我宁愿不给真实世界的用户创建数据库的访问权限

无论如何,我通过使用
DropCreateDatabaseIfModelChanges
初始值设定项并强制进行如下初始化,解决了我希望
UserProfile
(和相关表)创建数据库的具体问题:

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);
    }
}
public SimpleMembershipInitializer()
{
#如果调试
SetInitializer(新的DropCreateDatabaseIfModelChanges());
#否则
Database.SetInitializer(null);
#恩迪夫
尝试
{
使用(var context=new DataContext())
{
如果(!context.Database.Exists())
{
((IObjectContextAdapter)context.ObjectContext.CreateDatabase();
}
context.Database.Initialize(true);
}
WebSecurity.InitializeDatabaseConnection(“DefaultConnection”、“UserProfile”、“UserId”、“EmailAddress”、autoCreateTables:true);
}
捕获(例外情况除外)
{
抛出新的InvalidOperationException(“无法初始化ASP.NET简单成员身份数据库。有关详细信息,请参阅http://go.microsoft.com/fwlink/?LinkId=256588“,ex);
}
}
。。这是可行的,非常适合开发,但在实践中非常无用,因为如果模型发生变化,它将从零开始删除数据库并重新创建它。对我来说,这使得整个代码第一次实践在其默认形式下几乎毫无用处,我可能最终会返回到从DB edmx生成


仍在创建的
UserProfile
表背后的“秘密”是
WebSecurity.InitializeDatabaseConnection
将根据您传递到表中的字段初始化不存在的表,这就是创建
电子邮件地址而不是
UserName
的原因,因为我在这里更改了它。

1-您需要启用迁移,最好是使用EntityFramework 5。在NuGet软件包管理器中使用
启用迁移

2-移动你的

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true); 
到您的MVCAPP/Migrations/Configuration.cs类中的种子方法

    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"});
    }
现在EF5将负责创建您的UserProfile表,完成此操作后,您将调用WebSecurity.InitializeDatabaseConnection以仅向已创建的UserProfile表注册SimpleMembershipProvider,并告诉SimpleMembershipProvider哪列是用户ID和用户名。我还展示了一个示例,说明了如何在Seed方法中添加用户、角色,以及如何将这两个角色与自定义UserProfile属性/字段关联,例如用户的手机(号码)

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

有关其他参考资料,请参阅本文的源代码:

我也有同样的问题。我向中添加了代码,以便迁移正好发生在SimpleMembershipInitializer中的“CreateDatabase”之前

这解决了我的问题,只是我相信现在我的迁移将应用于Azure,而不管发布配置文件中的设置如何

  private class SimpleMembershipInitializer
    {
        public SimpleMembershipInitializer()
        {
            Database.SetInitializer<WomContext>(null);

            // forcing the application of the migrations so the users table is modified before
            // the code below tries to create it. 
            var migrations = new MigrateDatabaseToLatestVersion<WomContext, Wom.Migrations.Configuration>();
            var context = new WomContext(); 
            migrations.InitializeDatabase(context); 

            try
            {....
私有类SimpleMembershipInitializer
{
公共SimpleMembershipInitializer()
{
Database.SetInitializer(null);
//强制应用迁移,以便在迁移之前修改用户表
//下面的代码试图创建它。
var migrations=new MigrateDatabaseToLatestVersion();
var context=new WomContext();
迁移。初始化数据库(上下文);
尝试
{....

如果您没有计划在系统上线后进行更改,而这只是在开发过程中发生的,并且不希望启用迁移。请尝试截断表\uu MigrationHistory

truncate table __MigrationHistory

看起来很奇怪。这是可重复的吗?例如,清理并重建所有内容,仔细检查结果。你看的是正确的数据库吗?@HenkHolterman不幸的是,在过去的两天里,我一直在为此发疯,我甚至试着用它自己的名称为每一列添加属性,但它们根本不存在。更糟糕的是,
UserId
EmailAddress
(或我将其重命名为的任何名称)都很好。@Henkholtman还应该注意,我尝试在一个全新的项目上更改此表,只是作为一个测试,它具有sa