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的属性/
看来我可能终于得到了这个,它可能只是一个巨大的误解.
事实证明,我期望((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
,因为我在此更改了它.