C
C#8mo ago
Matney

❔ EF blowing up trying to insert a relationship that already exists

Code and question are in the text file
15 Replies
JakenVeina
JakenVeina8mo ago
var thing = context.Things.Single(t => t.Id == 1);

var thingCopy = new Thing()
{
Name = thing.Name,
Attributes = thing.Attributes
};
var thing = context.Things.Single(t => t.Id == 1);

var thingCopy = new Thing()
{
Name = thing.Name,
Attributes = thing.Attributes
};
don't do this this is not how EF works this is you telling EF to create a new Thing record, not to update an existing Thing record
Matney
Matney8mo ago
In that thingCopy is a new Thing record? I know that much... I probably should have specified that I'm doing that to bind thingCopy to some Blazor components, and I want to be able to Cancel out without modifying the original thing object. Is it possible to revert changes on an unsaved EF entity?
JakenVeina
JakenVeina8mo ago
Cancel out without modifying the original thing object
in what regard? if you don't want to modify the original Thing object, then don't never expose it to the UI
Matney
Matney8mo ago
Yeah, I'm not -- that's what the copy is for.
JakenVeina
JakenVeina8mo ago
the copy is for the UI?
Matney
Matney8mo ago
Yeah
JakenVeina
JakenVeina8mo ago
then why are you trying to save it?
Matney
Matney8mo ago
I want to save the changes made to the copy -- as a potentially discardable stand-in for the original thing -- back to the original thing record.
JakenVeina
JakenVeina8mo ago
then save changes made to the copy
Matney
Matney8mo ago
That's what I'm trying to do
JakenVeina
JakenVeina8mo ago
public async Task OnSaveButtonClickedAsync()
{
using var context = _contextFactory.CreateDbContext();
var thing = context.Things.Find(_currentThing.Id);

thing.Name = _currentThing.Name;

var existingAttributes = await context.Attributes
.Where(attribute => attribute.ThingId == _currentThing.Id)
.ToListAsync();

foreach(var attribute in _currentThing.Attributes)
if (!existingAttributes.Any(existingAttribute => existingAttribute.Name == attribute.Name))
context.Attributes.Add(new Attribute()
{
Name = attribute.Name,
ThingId = _currentThing.Id
});

foreach(var existingAttribute in existingAttributes)
if (!_currentThing.Attributes.Any(attribute => attribute.Name == existingAttribute.Name))
context.Attributes.Remove(existingAttribute);

await context.SaveChangesAsync();
}
public async Task OnSaveButtonClickedAsync()
{
using var context = _contextFactory.CreateDbContext();
var thing = context.Things.Find(_currentThing.Id);

thing.Name = _currentThing.Name;

var existingAttributes = await context.Attributes
.Where(attribute => attribute.ThingId == _currentThing.Id)
.ToListAsync();

foreach(var attribute in _currentThing.Attributes)
if (!existingAttributes.Any(existingAttribute => existingAttribute.Name == attribute.Name))
context.Attributes.Add(new Attribute()
{
Name = attribute.Name,
ThingId = _currentThing.Id
});

foreach(var existingAttribute in existingAttributes)
if (!_currentThing.Attributes.Any(attribute => attribute.Name == existingAttribute.Name))
context.Attributes.Remove(existingAttribute);

await context.SaveChangesAsync();
}
Matney
Matney8mo ago
Thank you. 😄
JakenVeina
JakenVeina8mo ago
this highlights the fact that you shouldn't be using Thing as your data model for the UI that's your data model for storage
Matney
Matney8mo ago
Fair
Accord
Accord8mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.