带有跟踪对象的EF Core更新

时间:2019-10-31 23:40:25

标签: c# entity-framework-core aspnetboilerplate

我使用ABP框架,我确实在更新问题上苦苦挣扎。我使用实体frmaework核心。

我将尽我所能去弄清楚。

我有一个类别表,其中包含类别名称和类别详细信息。

然后我要构建一个有角度的UI,该UI可以选择类别并将其存储在成就对象中。

那我的目标是存储成就和类别。

然后,我创建了一个表AccomplishementCategoryCustoms。

所以我的模型如下:

[Table("Accomplishments")]
public class Accomplishment : AuditedEntity 
{

    [Required]
    public virtual string Name { get; set; }

   public List<AccomplishementCategoryCustom> Categories { get; set; }
}

[Table("AccomplishementCategoryCustoms")]
public class AccomplishementCategoryCustom : CreationAuditedEntity 
{


    public virtual int? CategoryId { get; set; }

    [ForeignKey("CategoryId")]
    public Category CategoryFk { get; set; }

    public virtual int? AccomplishmentId { get; set; }

    [ForeignKey("AccomplishmentId")]
    public Accomplishment AccomplishmentFk { get; set; }

}

我在类别和AccomplishementCategoryCustoms之间没有关系。

然后当我插入它时效果很好。

当我更新并添加包含时,出现以下错误:

With include

当我更新时没有包含我会出现错误:

  

Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时发生错误。有关详细信息,请参见内部异常。 ---> System.Data.SqlClient.SqlException:当IDENTITY_INSERT设置为OFF时,无法为表'AccomplishementCategoryCustoms'中的标识列插入显式值。

最后,模型构建器如下:

 migrationBuilder.CreateTable(
            name: "AccomplishementCategoryCustoms",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                CreationTime = table.Column<DateTime>(nullable: false),
                CreatorUserId = table.Column<long>(nullable: true),
                CategoryId = table.Column<int>(nullable: true),
                AccomplishmentId = table.Column<int>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_AccomplishementCategoryCustoms", x => x.Id);
                table.ForeignKey(
                    name: "FK_AccomplishementCategoryCustoms_Accomplishments_AccomplishmentId",
                    column: x => x.AccomplishmentId,
                    principalTable: "Accomplishments",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
                table.ForeignKey(
                    name: "FK_AccomplishementCategoryCustoms_Categories_CategoryId",
                    column: x => x.CategoryId,
                    principalTable: "Categories",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });

        migrationBuilder.CreateIndex(
            name: "IX_AccomplishementCategoryCustoms_AccomplishmentId",
            table: "AccomplishementCategoryCustoms",
            column: "AccomplishmentId");

        migrationBuilder.CreateIndex(
            name: "IX_AccomplishementCategoryCustoms_CategoryId",
            table: "AccomplishementCategoryCustoms",
            column: "CategoryId");
    }

我希望它将有足够详细的修复信息,因为很长一段时间以来我一直在苦苦挣扎,无法解决问题。

2 个答案:

答案 0 :(得分:0)

好,所以我尝试了以下代码:

  var accomplishment = _accomplishmentRepository.GetAll().AsNoTracking().Where(a => 
  a.Id ==input.Id.Value)
  .Include(a => a.Categories)
  .FirstOrDefault();

  var updatedEntity =  ObjectMapper.Map(input, accomplishment);

   await _accomplishmentRepository.UpdateAsync(updatedEntity);

我没有错误了 更新得很好。

但是,如果我在用户界面中取消选择一个自定义类别并进行更新,则应该删除数据库中的行。

很遗憾,更改未反映在数据库中。该行没有更改。

然后我尝试附加并设置修改后的内容,但出现以下错误:

enter image description here

如何解决此问题?

我真的不知道如何解决它。

答案 1 :(得分:0)

根据您的答案,假设_dbContextProvider.GetDbContext(Abp.MultiTenancy.MultiTenancySides.Host)返回您要定位的数据库上下文(我从您的答案中得出),您可以使用以下代码来保持对成就的更改,包括添加或删除类别,假设以及ObjectMapper.Map(input, accomplishment)是使用输入对从存储库接收的成就进行更改的原因,还假设ObjectMapper.Map(input, accomplishment)返回的是实体类型。

async Task Update(CreateOrEditAccomplishmentsDto input)
{
    var context = _dbContextProvider.GetDbContext(Abp.MultiTenancy.MultiTenancySides.Host);
    context.Entry(ObjectMapper.Map(input, _accomplishmentRepository.GetAll().Where(a => a.Id == input.Id.Value).Include(a => a.Categories).FirstOrDefault())).State = EntityState.Modified;
    await context.SaveChangesAsync();
}

从技术上讲,该行的context.Entry(...).State = EntityState.Modified部分是多余的,但是我不确定您提供的任何内容的实现,因此我考虑了上下文实际上并没有从中跟踪返回的对象。致电Map

如果由于上下文已经跟踪id具有相同值的实体而遇到异常,请删除以下行。

context.Entry(ObjectMapper.Map(input, _accomplishmentRepository.GetAll().Where(a => a.Id == input.Id.Value).Include(a => a.Categories).FirstOrDefault())).State = EntityState.Modified;

然后,在调用SaveChangesAsync之前的位置添加以下行。

ObjectMapper.Map(input, _accomplishmentRepository.GetAll().Where(a => a.Id == input.Id.Value).Include(a => a.Categories).FirstOrDefault());