当我想引用现有对象时,身份框架会尝试插入新对象
Identity framework tries to insert new object when I want to reference an existing object
我正在使用 blazer 和身份框架制作一个网络应用程序。我希望对象 BoardYear
与作为主席的 Member
具有一对一的关系,这是一个 IdentityUser class 并通过下拉列表选择。
当我尝试插入一个新的 BoardYear
并且令人兴奋的 Member
作为主席时,我得到以下 SQL 异常。
SqlException: Violation of PRIMARY KEY constraint 'PK_AspNetUsers'. Cannot insert duplicate key in object 'dbo.AspNetUsers'. The duplicate key value is (de20c079-ed99-4bf9-9474-d8eb1a05b5b6).
似乎 Entity Framework 想将引用的 Member
添加到数据库中,这是不可能的,因为它已经存在。
会员class:
public class Member : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Guid? ChairmanBoardYearId { get; set; }
public BoardYear ChairmanBoardYear { get; set; }
...
}
董事会年class:
public class BoardYear
{
[Key]
public Guid BoardYearId { get; set; }
[DataType(DataType.Date)]
public DateTime StartDate { get; set; }
[DataType(DataType.Date)]
public DateTime EndDate { get; set; }
public Member Chairman { get; set; }
}
关系在 dbcontext 中配置如下:
public class ApplicationDbContext : IdentityDbContext<Member>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<BoardYear>()
.HasOne(m => m.Chairman)
.WithOne(b => b.ChairmanBoardYear)
.HasForeignKey<Member>(m => m.ChairmanBoardYearId);
base.OnModelCreating(builder);
}
public DbSet<BoardYear> BoardYears { get; set; }
public DbSet<Commission> Commissions { get; set; }
public DbSet<CommissionFine> CommissionFines { get; set; }
public DbSet<MemberFine> MemberFines { get; set; }
public DbSet<Meeting> Meetings { get; set; }
public DbSet<MeetingFile> MeetingFiles { get; set; }
public DbSet<MemberSanction> MemberSanctions { get; set; }
public DbSet<CommissionSanction> CommissionSanctions { get; set; }
public DbSet<YearGroup> YearGroups { get; set; }
public DbSet<CommissionList> CommissionLists { get; set; }
}
编辑下拉列表后,主席在剃须刀页面中的分配方式如下(我可以看到它获得了正确的成员):
async void OnBoardUserChange()
{
Member selectedMember = await MemberService.FindMember(selectedChairmanId);
curBoardYear.Chairman = selectedMember;
}
然后在下面的服务中放入数据库:
public class BoardYearService
{
private readonly IDbContextFactory<ApplicationDbContext> _contextFactory;
private readonly DidaDbContext _db;
public BoardYearService(IDbContextFactory<ApplicationDbContext> contextFactory)
{
_contextFactory = contextFactory;
}
public async Task<int> Create(BoardYear boardYear)
{
using (var ctx = _contextFactory.CreateDbContext())
{
CommissionList boardYearCommissionList = new CommissionList();
boardYear.CommissionList = boardYearCommissionList;
ctx.BoardYears.Add(boardYear);
return await ctx.SaveChangesAsync();
}
}
}
问题是您从 MemberService.FindMember 使用的任何上下文实例中检索了用户,但在添加到新上下文实例的 BoardYear 中引用了它。
添加 BoardYear 的第二个上下文实例未跟踪会员,因此假设它是一个添加项。
要么使用通过同一上下文实例检索并持久保存的数据执行整个操作,要么只使用 BoardYear 上的 Id 字段而不是导航 属性。
我正在使用 blazer 和身份框架制作一个网络应用程序。我希望对象 BoardYear
与作为主席的 Member
具有一对一的关系,这是一个 IdentityUser class 并通过下拉列表选择。
当我尝试插入一个新的 BoardYear
并且令人兴奋的 Member
作为主席时,我得到以下 SQL 异常。
SqlException: Violation of PRIMARY KEY constraint 'PK_AspNetUsers'. Cannot insert duplicate key in object 'dbo.AspNetUsers'. The duplicate key value is (de20c079-ed99-4bf9-9474-d8eb1a05b5b6).
似乎 Entity Framework 想将引用的 Member
添加到数据库中,这是不可能的,因为它已经存在。
会员class:
public class Member : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Guid? ChairmanBoardYearId { get; set; }
public BoardYear ChairmanBoardYear { get; set; }
...
}
董事会年class:
public class BoardYear
{
[Key]
public Guid BoardYearId { get; set; }
[DataType(DataType.Date)]
public DateTime StartDate { get; set; }
[DataType(DataType.Date)]
public DateTime EndDate { get; set; }
public Member Chairman { get; set; }
}
关系在 dbcontext 中配置如下:
public class ApplicationDbContext : IdentityDbContext<Member>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<BoardYear>()
.HasOne(m => m.Chairman)
.WithOne(b => b.ChairmanBoardYear)
.HasForeignKey<Member>(m => m.ChairmanBoardYearId);
base.OnModelCreating(builder);
}
public DbSet<BoardYear> BoardYears { get; set; }
public DbSet<Commission> Commissions { get; set; }
public DbSet<CommissionFine> CommissionFines { get; set; }
public DbSet<MemberFine> MemberFines { get; set; }
public DbSet<Meeting> Meetings { get; set; }
public DbSet<MeetingFile> MeetingFiles { get; set; }
public DbSet<MemberSanction> MemberSanctions { get; set; }
public DbSet<CommissionSanction> CommissionSanctions { get; set; }
public DbSet<YearGroup> YearGroups { get; set; }
public DbSet<CommissionList> CommissionLists { get; set; }
}
编辑下拉列表后,主席在剃须刀页面中的分配方式如下(我可以看到它获得了正确的成员):
async void OnBoardUserChange()
{
Member selectedMember = await MemberService.FindMember(selectedChairmanId);
curBoardYear.Chairman = selectedMember;
}
然后在下面的服务中放入数据库:
public class BoardYearService
{
private readonly IDbContextFactory<ApplicationDbContext> _contextFactory;
private readonly DidaDbContext _db;
public BoardYearService(IDbContextFactory<ApplicationDbContext> contextFactory)
{
_contextFactory = contextFactory;
}
public async Task<int> Create(BoardYear boardYear)
{
using (var ctx = _contextFactory.CreateDbContext())
{
CommissionList boardYearCommissionList = new CommissionList();
boardYear.CommissionList = boardYearCommissionList;
ctx.BoardYears.Add(boardYear);
return await ctx.SaveChangesAsync();
}
}
}
问题是您从 MemberService.FindMember 使用的任何上下文实例中检索了用户,但在添加到新上下文实例的 BoardYear 中引用了它。
添加 BoardYear 的第二个上下文实例未跟踪会员,因此假设它是一个添加项。
要么使用通过同一上下文实例检索并持久保存的数据执行整个操作,要么只使用 BoardYear 上的 Id 字段而不是导航 属性。