C
C#8mo ago
Angius

Is there any way to *conditionally* set a property with EF `.ExecuteUpdateAsync()`?

Right now, I'm doing
var thing = await _ctx.Things.FirstOrDefaultAsync(t => t.Id == req.Id);
if (thing.Name != req.Name) thing.Name = req.Name;
if (thing.Count != req.Count) thing.Count = req.Count;
await _ctx.SaveChangesAsync();
var thing = await _ctx.Things.FirstOrDefaultAsync(t => t.Id == req.Id);
if (thing.Name != req.Name) thing.Name = req.Name;
if (thing.Count != req.Count) thing.Count = req.Count;
await _ctx.SaveChangesAsync();
but I'm not sure how would I do something similar, as in, something that avoids setting x.Name = x.Name, with the Execute method. Something like
var rows = await _ctx.Things.Where(t => t.Id == req.Id)
.ExecuteUpdateAsync(props => props
.SetPropertyIf(t => t.Name != req.Name, t => t.Name, req.Name)
.SetPropertyIf(t => t.Count != req.Count, t => t.Count, req.Count))
var rows = await _ctx.Things.Where(t => t.Id == req.Id)
.ExecuteUpdateAsync(props => props
.SetPropertyIf(t => t.Name != req.Name, t => t.Name, req.Name)
.SetPropertyIf(t => t.Count != req.Count, t => t.Count, req.Count))
but no such thing seems to exist.
11 Replies
Bailey
Bailey8mo ago
I do not know what you exactly need. However the object is tracked. so if you set the value and it is the same. EF will notice that. Save wont do anything. Before you save you can use the property in the _ctx to check if there are any changes var thing = await _ctx.Things.FirstOrDefaultAsync(t => t.Id == req.Id); thing.Name = req.Name; thing.Count = req.Count; await _ctx.SaveChangesAsync(); // only saves if there are any changes. You //can also check for changes using: if (_ctx.ChangeTracker.HasChanges()) await _ctx.SaveChangesAsync();
Angius
Angius8mo ago
Yes, which is why I'm doing it this way But I'd like to start using the .Execute method here to save on a database call
Bailey
Bailey8mo ago
the code below essantial does the same. The object is taken. The values are updated and no if functions required var thing = await _ctx.Things.FirstOrDefaultAsync(t => t.Id == req.Id); thing.Name = req.Name; thing.Count = req.Count; if (_ctx.ChangeTracker.HasChanges()) await _ctx.SaveChangesAsync(); you can also use sql commands with EF. but its build for not using sql _ctx.ExecuteSql
unhAPI
unhAPI8mo ago
what sql would this translate to, an inline if? i don't think i have ever seen that but i could be wrong
Angius
Angius8mo ago
It would just not add a set clause to the resulting SQL
unhAPI
unhAPI8mo ago
have you tried if ?: is translated?
Angius
Angius8mo ago
Though... I guess it wouldn't know without executing some other query Just a simple bool would also work, I guess
var rows = await _ctx.Things.Where(t => t.Id == req.Id)
.ExecuteUpdateAsync(props => props
.SetPropertyIf(req.Name is not null, t => t.Name, req.Name)
.SetPropertyIf(req.Count is not null, t => t.Count, req.Count))
var rows = await _ctx.Things.Where(t => t.Id == req.Id)
.ExecuteUpdateAsync(props => props
.SetPropertyIf(req.Name is not null, t => t.Name, req.Name)
.SetPropertyIf(req.Count is not null, t => t.Count, req.Count))
unhAPI
unhAPI8mo ago
with just a null condition (on external value) you could make an extension (to add the expression)
Angius
Angius8mo ago
In case req.Name is null it would generate
UPDATE things t
WHERE t.Id = @id
SET t.Count = @count
UPDATE things t
WHERE t.Id = @id
SET t.Count = @count
If neither is null,
UPDATE things t
WHERE t.Id = @id
SET t.Count = @count, t.Name = @name
UPDATE things t
WHERE t.Id = @id
SET t.Count = @count, t.Name = @name
Huh, an extension method on the expression, maybe?
unhAPI
unhAPI8mo ago
that's what i said
Angius
Angius8mo ago
Yeah That could work
Want results from more Discord servers?
Add your server