Reputation: 7073
I am working on Code First , EF 6.0 and trying to implement Many to Many relationship between Request and Tag tables.
The relationships are set correctly as:
HasMany(b => b.Tags).WithMany().Map(mc => mc.MapLeftKey("RequestID").MapRightKey("TagID").ToTable("requesttags"));
Everything looks alright. However, when it comes to insert tags against Request, I inserting in three ways:
> if (request.Tags == null)
> {
> entity.Tags = new List<Tag>();
> }
> // 1 way get the tag and then insert.
> var tag = _tagService.Get(1);
// 2 and 3 way hard code id with the name.
> var tags = new List<Tag> {tag, new Tag {Name = ".Net", ID = 2}, new Tag {Name = "C#"}};
>
> request.Tags.AddRange(tags);
The insert operation is performed. However, when I see the end result: the first tag has made a reference correctly. However for two tags, even though ID and Names are matching, still it is creating a new record in Tag table and making a reference.
My thought are because the first tag object is get from the database and it is attached. But why do I have to attach?
How can I solve this?
Upvotes: 0
Views: 62
Reputation: 14640
But why do I have to attach?
Because they are disconnected objects and will be treated as new objects. The moment you add the tags
into request.Tags
, both of them will be marked as Added because EF doesn't know that both of them are existing entities.
You can check the state of each tag by simply loop the Tags
.
request.Tags.AddRange(tags);
foreach(var tag in tags)
{
Console.WriteLine(dbContext.Entry(tag).State);
}
The output should be like:
Unchanged
Added
Added
How can I solve this?
Just Attach
it or mark it as Unchanged
for the disconnected objects.
dbContext.Entry(tags[1]).State = EntityState.Unchanged;
// equals to dbContext.Set<Tag>().Attach(tags[1]);
dbContext.Entry(tags[2]).State = EntityState.Unchanged;
// equals to dbContext.Set<Tag>().Attach(tags[2]);
And make sure both entities are really existing entities, if not DbUpdateException
will be thrown when calling SaveChanges
.
Upvotes: 1