实体框架代码优先问题(SimpleMembership UserProfile 表) [英] Entity Framework Code-First Issues (SimpleMembership UserProfile table)

查看:30
本文介绍了实体框架代码优先问题(SimpleMembership UserProfile 表)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

If you've used ASP.NET MVC 4 you'll notice that the default for an Internet Application is to use the SimpleMembership provider, this is all well and good and works fine.

问题与默认数据库生成有关,他们为 UserProfile 定义了一个 POCO,如下所示:

The issue comes with the default database generation, they have a POCO for UserProfile defined like so:

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

...然后像这样生成:

.. which is then generated like this:

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

这很好用,数据库生成得很好并且没有问题.但是,如果我要像这样更改 POCO 并删除数据库:

This works fine, the database is generated just fine and works without issue. However, if I am to change the POCO like this and delete the database:

[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; }
}

仅生成前 2 列,UserIdEmailAddress.它在代码方面工作得很好(谈论登录/注册),但显然我的其他用户数据都没有被存储.

Only the first 2 columns are generated, UserId and EmailAddress. It works just fine code-wise (talking login/registration), but obviously none of my other user data is stored.

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

Am I missing something here? Surely it should generate the database based off the whole UserProfile object.

推荐答案

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

It seems I may have finally got this, and it may have just been one giant misunderstanding.

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

As it turns out, I was expecting ((IObjectContextAdapter)context).ObjectContext.CreateDatabase(); to do what it simply doesn't, which is create all of the tables in the database that don't exist, or simply update them if they do and they're different.

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

What actually happens is that it literally runs a CREATE DATABASE statement, which to me is the most useless thing ever. Unless you're working in a really strange environment, you will always have a database on the off and so it would always exist (and subsequently the table creation would never happen!), I'd rather not be giving real-world users access to create a database anyway.

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

Anyway, I solved my specific issue of wanting UserProfile (and related tables) to create the database by using the DropCreateDatabaseIfModelChanges initializer, and forcing an initialization like 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);
    }
}

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

.. this works and is perfect for development but is pretty useless in practice since it will literally drop the database and recreate it from scratch if the model changes. To me, this makes the whole code-first practice almost useless in it's default form and I'll probably end up reverting back to a from-DB edmx generation.

仍在创建的 UserProfile 表背后的谜团"是 WebSecurity.InitializeDatabaseConnection 将根据您传入的字段初始化该表(如果该表不存在)

The "mystery" behind the UserProfile table still being created is that WebSecurity.InitializeDatabaseConnection will initialise the table if it doesn't exist based on the fields you pass into it, which is why the EmailAddress was created instead of UserName, because I had changed it in this.

这篇关于实体框架代码优先问题(SimpleMembership UserProfile 表)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆