C# 实体框架代码第一个问题(SimpleMembership UserProfile表)
如果您使用过ASP.NET MVC 4,您会注意到Internet应用程序的默认设置是使用SimpleMembership提供程序,这一切都很好,而且工作正常 该问题与默认数据库生成有关,它们有一个用于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)]
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