从基本 asp.net 标识用户创建继承用户



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

这个例子已经被非常精简了,但应该提供足够的信息,说明无法创建具体用户(例如供应商的客户)。似乎我需要使用 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<Customer> CustomerCollection { get; set; }
      public DbSet<Supplier> SupplierCollection { get; set; }
 }

引发异常的种子类

 public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
 {
    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. 我总是希望将一种用户类型(例如供应商的客户)与身份用户相关联。我虽然关于使用界面,但这不起作用。
  2. 如果我还在用户类型上添加对 IdentityUser 的虚拟引用,我会得到"无法确定类型"ApplicaitonUser"和"供应商"之间关联的主端。此关联的主体端必须使用关系流畅 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; }*
 }
**

类身份用户(有效)**

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

类身份用户(我想要的)**

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

数据库上下文类

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

播种类**

 public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
 {
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<ApplicationUser>
{
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Supplier> Suppliers { get; set; }
}
public class ApplicationDbInitializer
             : DropCreateDatabaseAlways<ApplicationDbContext>
{
    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
}

免责声明:这不是一个"复制和粘贴"示例,应该只是让您了解不同的方法。

我刚刚解决了类似的问题。我在我的应用程序用户中创建了一个抽象类型的导航属性域用户(继承自身份用户)

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

域用户如下所示:

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

我从所有具体域用户类型的域用户继承:

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

在 OnModelCreate 方法的 DbContext 中,我将实体框架配置为将从 DomainUser 继承的所有实体存储在单独的表中(称为每个具体类型的表)。并在身份用户和域用户之间配置了一对一的关系:

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

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

相关内容

  • 没有找到相关文章