实体框架6,MVC5,ASP Identity 2.0。
我已按照这两个教程创建了Web应用程序的登录部分:part 1 - part 2
我在另一个库项目的IdentityUser Class中创建了自己的AppUser类。我还有来自IdentityDbContext的数据上下文
public class DataContext: IdentityDbContext<AppUser>
{
public DataContext(): base("DefaultConnection") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<AppUser>().Property(u => u.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);
base.OnModelCreating(modelBuilder);
}
}
public class AppUser : IdentityUser
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public override string Id { get; set; }
[Required]
[Display(Name ="First Name")]
[MaxLength(100)]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
[MaxLength(100)]
public string LastName { get; set; }
[MaxLength(100)]
public string Title { get; set; }
[Required(ErrorMessage = "Email is required.")]
[Display(Description = "Email")]
public override string Email { get; set; }
[MaxLength(20)]
public string Phone { get; set; }
[Range(0,9999)]
[Display(Name = "Extension")]
public int PhoneExtension { get; set; }
[Display(Name = "Active")]
[DefaultValue(true)]
public bool IsActive { get; set; }
}
当我运行种子方法时,我收到以下错误
System.Data.SqlClient.SqlException:无法将值NULL插入列&#39; Id&#39;,table&#39; CRM1.dbo.AspNetUsers&#39 ;;列不允许空值。 INSERT失败。 声明已经终止。
这是播种方法:
protected override void Seed(CRM.DAL.Data.DataContext context)
{
context.AccessLevels.AddOrUpdate(al => al.Label,
new Model.AccessLevel { AccessLevelID = 1, Label = "Admin", Description = "Full access to the CRM data" },
new Model.AccessLevel { AccessLevelID = 2, Label = "Customer Service", Description = "Full access to the CRM data" },
new Model.AccessLevel { AccessLevelID = 3, Label = "Sales", Description = "Full access to the CRM data" }
);
if (!(context.Users.Any(u => u.UserName == "admin@admin.com")))
{
var userStore = new UserStore<AppUser>(context);
var userManager = new UserManager<AppUser>(userStore);
var userToInsert = new AppUser
{
Id = "1",
FirstName = "Admin",
LastName = "Admin",
Title = "Administrator",
Email = "admin@admin.com",
PhoneExtension = 0,
IsActive = true,
AccessLevelID = 1,
EmailConfirmed = true,
PhoneNumberConfirmed = true,
TwoFactorEnabled = false,
LockoutEnabled = false,
AccessFailedCount = 0,
UserName = "admin"
};
userManager.Create(userToInsert, "password");
}
}
所以我得到一个值,但EF说它插入了NULL。我试过没有给Id任何价值,因为我认为EF会自动执行,但不会。
使用我的上下文为AspNetUser播种的方法是什么?我看到了不同的教程,但它不适用于我的扩展AppUser类和DataContext。
谢谢
答案 0 :(得分:2)
以下发生在我身上。我按照本指南将ASP.NET身份用户的主键从Guid更改为Int。
我已经进行了一些迁移,因此EF尝试将Id从nvarchar(128)更改为int。这有效,但Identity Specification
从未转为否。通过删除所有先前的迁移,删除数据库,然后为所有更改进行新迁移来解决此问题。由于我们处于早期开发阶段,这不是一个问题。
答案 1 :(得分:1)
从代码中删除此行:
modelBuilder.Entity<AppUser>().Property(u => u.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);
以及此User
的
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public override string Id { get; set; }
您不需要覆盖此属性,只需使用父级属性(实体框架将映射它)。
说明:当您配置Id
属性时,您告诉实体框架属性值来自数据库,因此它完全忽略您传递给的值插入数据库时的此属性。
另一方面,如果数据库表中的列没有默认值,它将失败,因为实体框架没有为它提供值。
所以你需要决定:你的表必须有一个默认值,或者你应该删除该字段的HasDatabaseGeneratedOption
选项。
问题是IdentityUser
使用string
作为密钥,通常为Guid
。由于EF不会自动为您生成Id
,而且您的列也不会,您可以为constructor
创建User
,如下所示:
public AppUser()
{
Id = Guid.NewGuid().ToString();
}
每当你创建一个新用户时,当你从你的上下文中读取一个现有用户时,它会有一个新的Guid
作为Id ....虽然你的构造函数会在被EF实例化时生成它,EF会然后从表中加载Id
值(忽略构造函数中提供的值)。
这意味着构造函数中的自动生成的Guid将仅用于新实例。