从基础asp.net标识用户创建inheritance用户

我有问题,我想在示例中创建N,两个用户对象(例如客户和供应商),这些都是asp.net IdentityUser对象所固有的。 除了来自IdentityUser的数据之外,这些对象具有非常不同的附加数据。 我想使用IdentityUser用户,因为这为我提供了一种灵活的方式来处理身份validation和授权。

这个例子已被删除,但应提供有关无法创建具体用户的充分信息(例如供应商的客户)。 我似乎需要使用UserManager对象,因为它还负责创建例如密码哈希和其他安全信息。

我收到以下错误:

{“附加’供应商’类型的实体失败,因为同一类型的另一个实体已经具有相同的主键值。当使用’附加’方法或将实体的状态设置为’未更改’或’已修改时,可能会发生这种情况’如果图中的任何实体具有冲突的键值。这可能是因为某些实体是新的并且还没有接收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态来跟踪图表然后根据需要将非新实体的状态设置为“未更改”或“已修改”。“}

IdentityUser固有的类

public class Customer : IdentityUser { public string CustomerProperty { get; set; } } public class Supplier : IdentityUser { public string SupplierProperty { get; set; } } 

数据库上下文类

  public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext() : base("ApplicationDbContext") { Database.SetInitializer(new ApplicationDbInitializer()); } public DbSet CustomerCollection { get; set; } public DbSet SupplierCollection { get; set; } } 

抛出exception的种子类

  public class ApplicationDbInitializer : DropCreateDatabaseAlways { protected override void Seed(ApplicationDbContext context) { var userStore = new UserStore(context); var userManager = new UserManager(userStore); // Seed customer user which inherents from asp.net IdentityUser var user = userManager.FindByEmail("customer@customer.com"); if (user == null) { user = new User() { UserName = "customer@customer.com", Email = "customer@customer.com" }; userManager.Create(user, userPassword); var customerUser = new Customer() { Id = user.Id, CustomerProperty = "Additional Info" }; context.Entry(customerUser).State = EntityState.Modified; context.SaveChanges(); } // Seed supplier user which inherents from asp.net IdentityUser var user = userManager.FindByEmail("supplier@supplier.com"); if (user == null) { user = new User() { UserName = "supplier@supplier.com", Email = "supplier@supplier.com" }; userManager.Create(user, userPassword); var supplierUser = new Supplier() { Id = user.Id, IBAN = "212323424342234", Relationship = "OK" }; context.Entry(supplierUser).State = EntityState.Modified; context.SaveChanges(); } } } 

****更新****

下面的解决方案有效,但我仍在努力解决两个问题:

  1. 我总是希望有一个用户类型(例如供应商的客户)与IdentityUser相关联。 我虽然使用接口,但这不起作用。
  2. 如果我还在用户类型上向IdentityUser添加虚拟引用,则会得到“无法确定类型’ApplicaitonUser’和’Supplier’之间关联的主要结束。 必须使用关系流畅API或数据注释显式配置此关联的主要结尾。 例外。

  public class Customer { [Key] public int CustomerId { get;set; } public string CustomerProperty { get; set; } *public virtual User User { get; set; }* } public class Supplier { [Key] public int SupplierId { get;set; } public string SupplierProperty { get; set; } *public virtual User User { get; set; }* } 

** Class IdentityUser(有效)**

 public class User : IdentityUser { public virtual Supplier Supplier { get; set; } public virtual Customer Customer { get; set; } } 

** Class IdentityUser(我想要的)**

 public class User : IdentityUser { public virtual IConcreteUser ConcreteUser{ get; set; } } 

数据库上下文类

  public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext() : base("ApplicationDbContext") { Database.SetInitializer(new ApplicationDbInitializer()); } public DbSet CustomerCollection { get; set; } public DbSet SupplierCollection { get; set; } } 

**播种class**

  public class ApplicationDbInitializer : DropCreateDatabaseAlways { protected override void Seed(ApplicationDbContext context) { var userStore = new UserStore(context); var userManager = new UserManager(userStore); var roleManager = new RoleManager(roleStore); var user = userManager.FindByEmail("customer@customer.com"); if (user == null) { user = new ApplicationUser() { UserName = "customer@customer.com", Email = "customer@customer.com" Customer = new Customer() { CustomerProperty = "Additional Info" } }; userManager.Create(user, userPassword); roleManager.AddUserToRole("Customer"); } user = userManager.FindByEmail("supplier@supplier.com"); if (user == null) { user = new ApplicationUser() { UserName = "supplier@supplier.com", Email = "supplier@supplier.com", Supplier = new Supplier() { IBAN = "212323424342234", Relationship = "OK" } }; userManager.Create(user, userPassword); roleManager.AddUserToRole("Supplier"); } } 

}

正如其他人一样,我认为这是一个设计问题。 有一些替代方法,如:

  1. 使用角色来定义“用户类型”(用户可以是供应商和客户)
  2. 使SupplierCustomer实体成为关系,而不是用户的扩展

例如:

 public class ApplicationUser : IdentityUser { public virtual Customer Customer { get; set; } public virtual Supplier Supplier { get; set; } } public class Customer { [Key] public int Id { get; set; } public virtual ApplicationUser User { get; set; } public string CustomerProperty { get; set; } } public class Supplier { [Key] public int Id { get; set; } public virtual ApplicationUser User { get; set; } public string SupplierProperty { get; set; } } public class ApplicationDbContext : IdentityDbContext { public DbSet Customers { get; set; } public DbSet Suppliers { get; set; } } public class ApplicationDbInitializer : DropCreateDatabaseAlways { protected override void Seed(ApplicationDbContext context) { var userStore = new UserStore(context); var userManager = new UserManager(userStore); var roleManager = new RoleManager(roleStore); var user = userManager.FindByEmail("customer@customer.com"); if (user == null) { user = new ApplicationUser() { UserName = "customer@customer.com", Email = "customer@customer.com" Customer = new Customer() { CustomerProperty = "Additional Info" } }; userManager.Create(user, userPassword); roleManager.AddUserToRole("Customer"); } user = userManager.FindByEmail("supplier@supplier.com"); if (user == null) { user = new ApplicationUser() { UserName = "supplier@supplier.com", Email = "supplier@supplier.com", Supplier = new Supplier() { IBAN = "212323424342234", Relationship = "OK" } }; userManager.Create(user, userPassword); roleManager.AddUserToRole("Supplier"); } } } 

在你的逻辑中,你可以做一些事情:

 if (User.IsInRole("Customer")) { // do something } 

免责声明 :这不是“复制和粘贴”示例,只是让您了解不同的方法。

我刚刚解决了类似的问题。 我在AppUser中创建了抽象类型DomainUser的导航属性(inheritance自Identity User)

 public class AppUser : IdentityUser { public DomainUser DomainUser { get; set; } } 

DomainUser看起来像这样:

 public abstract class DomainUser : IAggregateRoot { public Guid Id { get; set; } public AppUser IdentityUser { get; set; } } 

我在所有具体的域用户类型中inheritanceDomainUser:

 public class AdministrationUser : DomainUser { public string SomeAdministrationProperty { get; set; } } public class SupplierUser : DomainUser { public string SomeSupplierProperty { get; set; } } public class Customer : DomainUser { public string SomeCustomerProperty { get; set; } } 

在OnModelCreating方法的DbContext中,我将Entity Framework配置为将从DomainUserinheritance的所有实体存储在单独的表中(它称为Table per Concrete Type )。 并在IdentityUser和DomainUser之间配置一对一关系:

 modelBuilder.Entity() .Map(m => { m.MapInheritedProperties(); m.ToTable("AdministrationUsers"); }) .Map(m => { m.MapInheritedProperties(); m.ToTable("SupplierUsers"); }) .Map(m => { m.MapInheritedProperties(); m.ToTable("Customers"); }); modelBuilder.Entity() .HasRequired(domainUser => domainUser.IdentityUser) .WithRequiredPrincipal(groomUser => groomUser.DomainUser); 

此代码将“DomainUser_Id”列添加到表AspNetUsers,现在我可以访问AppUser中每个域用户和DomainUser导航属性中的IdentityUser导航属性。