C
C#ā€¢2y ago
dave1

ā” Struggling to delete a many to many relation

public async Task<IStatusCodeActionResult> Remove(long areaId, long houseId)
{
var area = await _context.Areas
.Include(s => s.Houses)
.FirstOrDefaultAsync(s => s.Id == areaId);

if (area == null)
return BadRequest("Area does not exist");

var house = await _context.Houses
.FirstOrDefaultAsync(s => s.Id ==houseId);

if (house == null)
return BadRequest("House does not exist");

var success = area.Houses.Remove(house);

if (success == false)
return BadRequest("House not found in this area");

_context.Areas.Update(area);

await _context.SaveChangesAsync();
public async Task<IStatusCodeActionResult> Remove(long areaId, long houseId)
{
var area = await _context.Areas
.Include(s => s.Houses)
.FirstOrDefaultAsync(s => s.Id == areaId);

if (area == null)
return BadRequest("Area does not exist");

var house = await _context.Houses
.FirstOrDefaultAsync(s => s.Id ==houseId);

if (house == null)
return BadRequest("House does not exist");

var success = area.Houses.Remove(house);

if (success == false)
return BadRequest("House not found in this area");

_context.Areas.Update(area);

await _context.SaveChangesAsync();
27 Replies
dave1
dave1OPā€¢2y ago
been looking at it for a long time now, just need a sanity check if that's how it should be, then i must have fucked up somewhere else i think i'm going to just delete it manually, no idea how to debug this it's supposed to simply remove that sepcific house from the area, it's a many to many
Tvde1
Tvde1ā€¢2y ago
when you fetch the Area, you are not including the list of houses. Do that through
await _context.Areas
.Include(x => x.Houses)
.FirstOrDefault(...);
await _context.Areas
.Include(x => x.Houses)
.FirstOrDefault(...);
You would see that every area you fetch has no houses, if you omit the .Include
dave1
dave1OPā€¢2y ago
sorry should have updated it, i have that in my current version now when i step debug through, i see it's removed it , i get no errors, but when i test the db after, that relation still exists
Tvde1
Tvde1ā€¢2y ago
_context.Areas.FirstOrDefaultAsync(s => s.Id == areaId);
_context.Areas.FirstOrDefaultAsync(s => s.Id == areaId);
will result into
SELECT TOP 1 *
FROM Areas
WHERE id == @areaId;
SELECT TOP 1 *
FROM Areas
WHERE id == @areaId;
and
_context.Areas
.Include(x => x.Houses)
.FirstOrDefaultAsync(s => s.Id == areaId);
_context.Areas
.Include(x => x.Houses)
.FirstOrDefaultAsync(s => s.Id == areaId);
will result into
SELECT *
FROM Areas a
WHERE id == @areaId
INNER JOIN Houses h
ON h.AreaId = a.Id
SELECT *
FROM Areas a
WHERE id == @areaId
INNER JOIN Houses h
ON h.AreaId = a.Id
dave1
dave1OPā€¢2y ago
aye i'm presuming that the change tracker needs some change to track, so removing nothing, it cant track that change
Tvde1
Tvde1ā€¢2y ago
you can try
public async Task<IStatusCodeActionResult> Remove(long areaId, long houseId)
{
var area = await _context.Areas
.Include(s => s.Houses)
.FirstOrDefaultAsync(s => s.Id == areaId);

if (area == null)
return BadRequest("Area does not exist");

var house = area.Houses.FirstOrDefault(s => s.Id ==houseId);

if (house == null)
return BadRequest("House does not exist");

var success = area.Houses.Remove(house);

if (success == false)
return BadRequest("House not found in this area");

await _context.SaveChangesAsync();
public async Task<IStatusCodeActionResult> Remove(long areaId, long houseId)
{
var area = await _context.Areas
.Include(s => s.Houses)
.FirstOrDefaultAsync(s => s.Id == areaId);

if (area == null)
return BadRequest("Area does not exist");

var house = area.Houses.FirstOrDefault(s => s.Id ==houseId);

if (house == null)
return BadRequest("House does not exist");

var success = area.Houses.Remove(house);

if (success == false)
return BadRequest("House not found in this area");

await _context.SaveChangesAsync();
it makes one less db call and the update is not necessary, savechanges will save everything you change to entities
dave1
dave1OPā€¢2y ago
oh you know, i have actually tried tha aswell hahaha i wasnt sure if it was required cheers, so ef context is doing more magic under the hood than i presumed, good to know
Tvde1
Tvde1ā€¢2y ago
yes, any entity you get from it will have its changes tracked (unless you explicitly tell it not to)
var area = await _context.Areas
.AsNoTracking()
.Include(s => s.Houses)
.FirstOrDefaultAsync(s => s.Id == areaId);
var area = await _context.Areas
.AsNoTracking()
.Include(s => s.Houses)
.FirstOrDefaultAsync(s => s.Id == areaId);
would make EF not track changes
dave1
dave1OPā€¢2y ago
ah i had assumed it was on the action of Update/Create etc. it was tracking from that point
Tvde1
Tvde1ā€¢2y ago
honestly I'm not sure why your original code didn't work. It feels as if it should also work
dave1
dave1OPā€¢2y ago
yeah you see i'm at that point aswell, i think i've fkd up the entities at least i know that side is fine cheers Tvde1, appreciated
Tvde1
Tvde1ā€¢2y ago
you think you messed up the entities?
dave1
dave1OPā€¢2y ago
maybe, that's the only other moving part, or maybe my test is wrong oh god, i think it's the test
Tvde1
Tvde1ā€¢2y ago
šŸ˜ happens to the best of us
dave1
dave1OPā€¢2y ago
yeah you helped me, cheers, hahah, in my test i'm creating the relation, then after hitting the endpoint i'm testing it again but i wasn't clearing the tracked values, i presumed once i saved async it was automatically clear šŸ¤¦ā€ā™‚ļø casual 4-6 hours in total time wasted on that
Tvde1
Tvde1ā€¢2y ago
I once spent 4 hours trying to figure out why my break point didn't get hit, turns out I was making HTTP calls to the test environment, not to my local api
dave1
dave1OPā€¢2y ago
oh yup, done that, more than once or wondering why nothings working because i've left a break point somewhere
Tvde1
Tvde1ā€¢2y ago
everyone messes up like that, the trick is that your brain will remember and you'll check stuff much sooner
dave1
dave1OPā€¢2y ago
and not noticed, though, not in c#
Tvde1
Tvde1ā€¢2y ago
then next time, a colleague asks you for help, you do the sanity checks and you save a lot of time
dave1
dave1OPā€¢2y ago
i'm only like 5 days in .net oh, we're switching over to c#, i'm the canary
Tvde1
Tvde1ā€¢2y ago
well great job learning Entity Framework so far and making tests!
dave1
dave1OPā€¢2y ago
new cto wants to move over, i figure, as long as its not my decision, i'm game, i like learning new systems/languages always tests, first thing i try and figure out how to do when learning a new thing xD it's strange how little literature there is around testing against a TestServer a lot of people saying to just mock EF w/e, but in making an API and basic crud i want to know something is stored.. testcontainers to the rescue anyway, no idea how i'm going to integrate that into the pipeline
Tvde1
Tvde1ā€¢2y ago
Integration tests in ASP.NET Core
Learn how integration tests ensure that an app's components function correctly at the infrastructure level, including the database, file system, and network.
Tvde1
Tvde1ā€¢2y ago
I have yet to dabble with actual integration tests like this
dave1
dave1OPā€¢2y ago
i've got two sets one where i inject EF and wrap my tests in transctions, they're my integration the other is using TestServer, where it spins up an instance and i can tests the endpoint, where you cant use transactions, obviously cos it's a different process(coming from a scripting language took me a minute to realise this) a long minute, as once it's built ,it's built, i can't just use the code that's in the request so currently for those webapp tests it spins up a test container per class (testcontainers https://dotnet.testcontainers.org/) it disposes of them after, it's pretty nifty and i can test the system properly, end to end (without the front end) either way, cheers for the help, i was tearing my last few hairs out
Accord
Accordā€¢2y 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.
Want results from more Discord servers?
Add your server