-->

EF Core 3.0 adding connected entity to collection

2020-07-20 00:02发布

问题:

I try to add entity through the navigation property of collection, but the following message comes up:

"Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions."

The models are:

SuggestionGroupDb:

public class SuggestionGroupDb
{
    public Guid Id { get; set; }

    [Required]
    public string UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual TeguUserDb User { get; set; }

    [Required(AllowEmptyStrings=false, ErrorMessage = "Required")]
    [StringLength(30, MinimumLength = 1, ErrorMessage = "Invalid")]
    public string Name { get; set; }

    public int OrderNo { get; set; }

    public virtual ICollection<SuggestionItemDb> Items { get; set; }
}

SuggestionItemDb:

public class SuggestionItemDb
{
    public Guid Id { get; set; }

    [Required]
    public Guid SuggestionGroupId { get; set; }
    [ForeignKey("SuggestionGroupId")]
    public virtual SuggestionGroupDb SuggestionGroup { get; set; }

    [Required(AllowEmptyStrings=false, ErrorMessage = "Required")]
    [StringLength(30, MinimumLength = 1, ErrorMessage = "Invalid")]
    public string Name { get; set; }

    public int OrderNo { get; set; }
}

SuggestionGroup Repository Update function (simplified):

    public async Task<SuggestionGroupRepositoryResult> UpdateAsync(string userid, SuggestionGroupDb suggestiongroup)
    {
        // Step 01 - Get the Entity
        var dbSuggestionGroup = await GetAsync(userid, suggestiongroup.Id, suggestiongroup.Name);

        // Step 02 - Update the items (just add one now)
        foreach (var item in suggestiongroup.Items)
        {
            var sidb = new SuggestionItemDb() {Id = item.Id, Name = item.Name, OrderNo = item.OrderNo, SuggestionGroupId = item.SuggestionGroupId};
            dbSuggestionGroup .Items.Add(sidb);
        }

        // Step 03 - Update the changes
        try
        {
            var updated = context.AccSuggestionGroups.Update(dbSuggestionGroup);
            await context.SaveChangesAsync();

            return new SuggestionGroupRepositoryResult("Valid") /*{SuggestionGroup = updated.Entity}*/;
        }
        catch (Exception e)
        {
            context.Reset();
            return new SuggestionGroupRepositoryResult("Failed", e.Message);
        }
    }

The problem is that SaveChanges throws and exception with the given message. Is it possible to update the SuggestionItems through the SuggestionGroup?

I am using EF Core 3.0 preview 6.

回答1:

Prior to EF Core 3.0, untracked entities discovered by the DetectChanges strategy (in your case, by adding an untracked entity to a collection) would automatically be in the Added state.

This is no longer the case. From Entity Framework Core 3.0 the entity will be automatically added in the Modified state.

Why

This change was made to make it easier and more consistent to work with disconnected entity graphs while using store-generated keys.

Source: EF Core 3.0 - Breaking Changes

You can force new untracked entities to be added in the Added state by configuring the key property to explicitly not use generated values.

For example:

public class SuggestionItemDb
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public Guid Id { get; set; }
}

Or using the fluent API

modelBuilder
    .Entity<SuggestionItemDb>()
    .Property(e => e.Id)
    .ValueGeneratedNever();