我遇到的问题是我想在示例中创建N,两个用户对象(例如Customer& Supplier),这些对象都是asp.net IdentityUser对象所固有的。除了来自IdentityUser的数据之外,这些对象具有非常不同的附加数据。我想使用IdentityUser用户,因为这样可以灵活地处理身份验证和授权。
此示例已被删除,但应提供有关无法创建具体用户的充分信息(例如,供应商的客户)。我似乎需要使用UserManager对象,因为它还负责创建密码哈希和其他安全信息。
我收到以下错误:
{"附加类型'供应商'失败,因为同一类型的另一个实体已具有相同的主键值。使用'附加'方法或将实体的状态设置为“未更改”#39;或者'修改'如果图中的任何实体具有冲突的键值。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,请使用'添加'方法或“添加”#39;实体状态跟踪图形,然后将非新实体的状态设置为“未更改”。或者'修改'酌情。"}
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();
}
}
}
****更新****
下面的解决方案有效,但我仍然在努力解决两个问题:
类
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");
}
}
}
答案 0 :(得分:8)
正如其他人一样,我认为这是一个设计问题。有一些替代方法,如:
Supplier
和Customer
实体成为关系而不是用户的扩展e.g:
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
}
免责声明:这不是“复制和粘贴”示例,只是让您了解不同的方法。
答案 1 :(得分:3)
我刚刚解决了类似的问题。我在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导航属性。