Updating Immutable object with ef
Hi guys, i have an immutable object, so if i want to update it i have to crate a new istance of it, when doing so i create conflicts with the original tracked object key id, can someone help me out with this? š
35 Replies
.ExecuteUpdateAsync()
maybe
If it's immutable, then the change tracker... cannot change changes
So the usual fetch -> modify -> save won't work
like i said:
you need to remove
AsNoTracking
and do it right šhei sorry i dont understand this will leave me with the problem that i get key conflict
no it won't
when creating a new one it wont but when updating the old one it does :C
no it won't
i must doing somthing wrong then wait i sec i implement it
yes, that's what I'm explaining.
that is the difference of AsNoTracking
now its tracking the Entity with Patricks code
that's what he wanted u to notice ;x (I think)
with this implementation, ef wont update the worker:
you need to read the code I posted and understand it
you need to use the tracked existing entity OR make a new one
not both.
post that code here.
i dont edit screenshots.
public async Task<(bool Created, WorkerResponse Worker)> UpsertWorkerAsync(UpsertWorkerRequest upsertWorker)
{
var worker = _context.Workers.FirstOrDefault(w => w.Id == upsertWorker.Id);
var updatedWorker = Worker.CreateWithId(upsertWorker.Id, upsertWorker.Name, upsertWorker.Role);
if (worker is not null)
{
worker = updatedWorker;
await _context.SaveChangesAsync();
return (false, updatedWorker);
}
else
{
_context.Workers.Add(updatedWorker);
await _context.SaveChangesAsync();
return (true, updatedWorker);
}
}
you only want to create a new entity where it's actually required, otherwise use the existing one.
i suspect the problem you have is trying to reuse
Worker.CreateWithId
when you shouldn't be.i want to do an upsertoperation that's my goal, if the entity does not exist create it if it does update it
im sorry i still dont understand :Smadge: what this should do?
i cant update properties like that directly, the object is immutable i must create a new istance
1. it tries to query an existing worker:
2. if the worker does not exist, it instantiates a new
Worker
entity and adds it to the context
3. if the worker does exist, and has been queried, no new worker is created
4. the relevant properties of the worker are updated in all pathways
that's not really how EF works šthe worker record has private setters and private parameterless ctor that's why im doing this
what could go wrong leaving this implementation like this? cause im getting the desired result this way
if they're private setters, make a method
there's some validation and calculation going on in the creation
ok
the object is already created so š
maybe i just did some horrible disign decisions, should i just make an anemic class with public props as my models?
no you don't get my point
the object already exists at the point of calling update
you either create it or query it
then should i insted of update it, first delete it and then create a new one if exists?
no....
:Smadge:
you realise that whatever
CreateWithId
does, EF doesn't do when you query the entity, right?
so these "calculations" have already occurred when you already inserted the entity, assuming you persist them to the db.
You don't need to do them again if you're querying an existing object from the database.
if the problem is that CreateWithId
is actually performing calculations for stuff that isn't persisted in the database, that is a design problem.i need to understand something, what if i have a record as an enitity with just and Id and Name, how can i update that record with ef?
you shouldn't use records as entities
if you absolutely must, I suppose you would need to use
ExecuteUpdateAsync
.context.Blogs
.Where(b => b.Rating < 3)
.ExecuteUpdate(setters => setters.SetProperty(b => b.IsVisible, false)); how does it works? does it use some kind of reflection to access even readonly fields?
If it's just a
?
or, nowadays,
Yes
they're asking about records
not classes
For a record, then yeah,
ExecuteUpdate()
But as you said, you usually wouldn't use immutable stuff like records for EF
It's easier to just mutate and saveok thx š then i need a class as a model and if i want something to be immutable i should use it in its properties
@Patrick @ZZZZZZZZZZZZZZZZZZZZZZZZZ what about this? this look reasonable?
doesn't matter what i say you won't do what i suggest anyway
so sure
š