Reputation: 33
I have a problem saving the changes to Database Context. When i don't save i can see that the listing status is successfully changed , but when i try to save it I get an error which is saying : " There is already an open DataReader associated with this Connection which must be closed first." And i don't know where that comes from. When i try to do it asynchronous i get the same error.
AdministratorController.cs
[Route("/Admin")]
[ApiController]
public class AdministratorController : Controller
{
private readonly dbContext _dbContext;
public AdministratorController(dbContext dbContext)
{
_dbContext = dbContext;
}
///////////////////////////////////
/// //
/// Accept or Reject Listings //
/// //
//////////////////////////////////
[HttpPost]
[Route("acceptListing/{listingId}")]
[AllowAnonymous]
//[Authorize(Roles="Administrator")]
public ActionResult AcceptList([FromRoute]int listingId)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
if (listingId == null)
{
return NotFound("Listing not found.");
}
foreach (Listing listing in _dbContext.Listings)
{
Console.WriteLine(listing.Status);
if(listing.Id == listingId)
{
if(listing.Status == ListingStatus.Accepted)
{
return BadRequest("Listing already accepted.");
}
else
{
listing.Status = ListingStatus.Accepted;
Console.WriteLine(listing.Status);
_dbContext.SaveChanges();
}
return Ok();
}
}
return BadRequest("Couldn't find right listing.");
}
Upvotes: 0
Views: 161
Reputation: 1660
Rather than looping through all listings looking for the one with the Id you want, just filter and get.
Listing? listing = _dbContext.Listings.FirstOrDefault(l => l.Id == listingId);
if (listing is null)
{
return BadRequest("Couldn't find right listing.");
}
if(listing.Status == ListingStatus.Accepted)
{
return BadRequest("Listing already accepted.");
}
listing.Status = ListingStatus.Accepted;
Console.WriteLine(listing.Status);
_dbContext.SaveChanges();
return Ok();
Upvotes: 1
Reputation: 1046
change the code like this :
var listings = _dbContext.Listings.Tolist();
foreach (Listing listing in listings)
{
Console.WriteLine(listing.Status);
if(listing.Id == listingId)
{
if(listing.Status == ListingStatus.Accepted)
{
return BadRequest("Listing already accepted.");
}
else
{
listing.Status = ListingStatus.Accepted;
Console.WriteLine(listing.Status);
_dbContext.Update(listing);
_dbContext.SaveChanges();
}
return Ok();
}
}
Upvotes: 0
Reputation: 141835
The problem here is that you are iterating the data being fetched from database and in the same time you are trying to save something from the same context. Quick fix is to use ToList
in foreach
:
foreach (Listing listing in _dbContext.Listings.ToList())
{
// ..
}
But in general you should not fetch everything from the database to process only one item. Just write query that will filter everything on database side. Something along this lines (not tested):
var listing = _dbContext.Listings.FirstOrDefault(l => l.Id == listingId);
if (listing is null)
{
return NotFound();
}
if (listing.Status == ListingStatus.Accepted)
{
return BadRequest("Listing already accepted.");
}
else
{
listing.Status = ListingStatus.Accepted;
Console.WriteLine(listing.Status);
_dbContext.SaveChanges();
}
return Ok();
Upvotes: 1