我构建了一个新的Web应用程序,它使用Visual Studio提供的模板并包含MVC和Web API。默认授权机制是Identity,数据库交互是使用Entity Framework和Code-first方法创建数据库完成的。
我有三个要求:
理论上,多个父母可以参考多个孩子,但是对于这个例子,我们只会将其视为一对多的关系。
在我的应用程序中,我需要ApplicationUser
有一个ChildUsers列表作为ApplicationUser
的集合,如下所示。
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string ShirtSize { get; set; }
public ICollection<ApplicationUser> Children { get; set; }
}
我希望这些用户可以访问,如上所示(ApplicationUser
的集合),而不是将Relationship
对象绑定在一起的集合,例如:
public class Relationship
{
public String ParentId { get;set; }
public String ChildId { get;set; }
}
是否可以在数据库中创建并存在新表,而无需使用代码优先模型来了解如何创建关系表?
这个问题的解决方案是什么?
答案 0 :(得分:0)
经过一些研究和实验,我找到了一些指导,以找到有效的解决方案。
为了创建一个中间表来维护关系,ApplicationDbContext
OnModelCreating
函数需要知道它应该是什么样子。我告诉它使用下面代码中显示的modelBuilder
创建一个未绑定到对象的新表。不幸的是,我没有指向我的文章的链接。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base( "DefaultConnection", throwIfV1Schema: false )
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
base.OnModelCreating( modelBuilder );
modelBuilder.Entity<ApplicationUser>()
.HasMany( p => p.ChildUsers )
.WithMany()
.Map( m =>
{
m.MapLeftKey( "Father_Id" );
m.MapRightKey( "Son_Id" );
m.ToTable( "father_son_relation" );
} );
}
}
此外,当您需要将Child添加到父ApplicationUser
时,您需要在插入时进行一些调整,以便正确更新数据库。我绝对希望UserManager
为我创建用户,但这意味着当我使用下面的代码将用户添加到我的Child列表中时,它会尝试再次添加它并抛出异常因为它已经存在。
var result = await UserManager.CreateAsync( user, model.Password );
var myUserId = User.Identity.GetUserId();
var users = AppDbContext.Users.Where( u => u.Id == myUserId ).Include( u => u.ChildUsers );
var u2 = users.First();
u2.ChildUsers.Add( user );
await AppDbContext.SaveChangesAsync();
找到this question后,我研究了EntityState
,发现在调用SaveChanges
之前添加以下行解决了异常,并且不再尝试再次添加它。
AppDbContext.Entry( user ).State = EntityState.Unchanged;
TADA !!!现在,使用EF从数据库中选择它们,然后可以使用以下代码:
AppDbContext.Users.Where( u => u.Id == myUserId ).Include( u => u.Children ).First();
因为我只获得一个级别的孩子,所以这样可以正常工作,之后你冒着循环引用的风险。
欢迎提出改进代码的意见和建议。