簡體   English   中英

從基礎asp.net標識用戶創建繼承用戶

[英]Creating inheritance users from base asp.net identity user

我有問題,我想在示例中創建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. 我總是希望有一個與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<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
}

免責聲明 :這不是“復制和粘貼”示例,只是讓您了解不同的方法。

我剛剛解決了類似的問題。 我在AppUser中創建了抽象類型DomainUser的導航屬性(繼承自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; }
}

我在所有具體的域用戶類型中繼承DomainUser:

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配置為將從DomainUser繼承的所有實體存儲在單獨的表中(它稱為Table per Concrete Type )。 並配置IdentityUser和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,現在我可以訪問AppUser中每個域用戶和DomainUser導航屬性中的IdentityUser導航屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM