简体   繁体   中英

Entity Framework - Can't Delete and Insert to DbContext in the same method

So the 3 tables I'm using are Event and Tag tables that have a many-to-many relationship, which is 'simulated' via a bridging table that has a one-to-many relationship with each table, EventTag , whose foreign keys make up a composite primary key.

In my code, I guess albeit very inefficient, I'm trying to delete entries from the EventTag table when adding Tag s to be associated with a particular Event or changing which existing tags are now associated with it.

The code below works fine when I only delete tags associated with an event or when I only add new tags, however when I add and delete tags in the same call, the tags only get deleted, and no changes are made to add the new ones.

I tried taking out the first call to context.SaveChanges(); putting it all in one (using DbContext ... ) block but neither seemed to work. I've no idea what the problem could be.

public async Task<string> Post(AddTagsRequest request)
    {
        string problem = "";
        try
        {
            using (DbContext context = new DbContext())
            {
                var eventtagstodelete =
                    await context.EventTags.Where(eventtag => eventtag.EventId == request.EventId).ToListAsync();
                foreach (var eventtagtodelete in eventtagstodelete)
                {
                    context.Entry(eventtagtodelete).State = EntityState.Deleted;
                }

                List<Tag> Tags = request.Tags.Select(tag => new Tag {Value = tag}).ToList();

                List<string> tagIds = new List<string>();

                foreach (var tag in Tags)
                {
                    List<Tag> foundTags = await context.Tags.Where(row => row.Value == tag.Value).ToListAsync();
                    if (foundTags.Count > 0)
                    {
                        tagIds.Add(foundTags.First().Id);
                    }
                    else
                    {
                        context.Tags.Add(new Tag
                        {
                            Value = tag.Value
                        });
                    }
                }

                foreach (var tagId in tagIds)
                {
                    context.EventTags.Add(new EventTag
                    {
                        TagId = tagId,
                        EventId = request.EventId
                    });
                }
                await context.SaveChangesAsync();
                return "success";
            }
        }
        catch (Exception e)
        {
            while(e.InnerException != null){
                e = e.InnerException;
            }
            return "failure - Message: " + e.Message;
        }
    }

public class AddTagsRequest
{
    public List<string> Tags { get; set; }
    public string EventId { get; set; }
}

public class Event : EntityData
{
    public string Name { get; set; }
}

public class Tag : EntityData
{
    public string Value { get; set; }
}

public class EventTag : EntityData
{
    public Event Event { get; set; }
    public string EventId { get; set; }
    public Tag Tag { get; set; }
    public string TagId { get; set; } 
}

    public EventTagConfig()
    {
        HasKey(eventTag => new { eventTag.EventId, eventTag.TagId });
    }

Update 1

Added Event , Tag , and EventTag classes, as well as the configuration class EventTagConfig to configure the EventTag table.

Changed code from 2 using and 2 context.SaveChanges(); to only 1 of each.

When I run it like this I get the following error:

Modifying a column with the 'Identity' pattern is not supported. Column: 'Id'. Table: 'CodeFirstDatabaseSchema.EventTag'.

There wasn't a problem with having multiple saves/contexts - I just did something stupid.

I actually removed the second using, and saved any time I needed to persist changes. The problem I had was in my if-else block I added the Id of an existing tag to the tagIds list but when adding another, I wasn't then adding the new Id to the list, so it wasn't adding the EventTag entry this time, but when I run it a second time, the 'new'-now-existing tag is found, and it's Id added to the list.

To fix I add all new tags to a list - newTagList , in the else block, then call context.Tags.AddRange(newTagList) , followed by context.SaveChanges() and then pull the Ids from the newTagList to be added to the EventTag table.

To note - @UrbanEsc that error I posted in the update came about as a result of the change suggested by @Henk_Holterman, and was due to entries marked with EntityState.Deleted not actually being deleted when the insert was called, thus giving that error.

Anyway, thanks for your help guys.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM