У меня проблема с сохранением изменений в контексте базы данных. Когда я не сохраняю, я вижу, что статус списка успешно изменен, но когда я пытаюсь сохранить его, я получаю сообщение об ошибке: «Уже есть открытый DataReader, связанный с этим соединением, который должен быть закрыт в первую очередь». И я не знаю, откуда это. Когда я пытаюсь сделать это асинхронно, я получаю ту же ошибку.
АдминистраторКонтроллер.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.");
}
Да, это его проблема, он повторяет список, изменяя их в том же цикле.





Проблема здесь в том, что вы повторяете данные, извлекаемые из базы данных, и в то же время пытаетесь сохранить что-то из того же контекста. Быстрое решение - использовать ToList в foreach:
foreach (Listing listing in _dbContext.Listings.ToList())
{
// ..
}
Но в целом вам не следует извлекать из базы данных все, чтобы обработать только один элемент. Просто напишите запрос, который будет фильтровать все на стороне базы данных. Что-то в этом роде (не проверено):
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();
изменить код следующим образом:
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();
}
}
Вместо того, чтобы перебирать все списки в поисках нужного идентификатора, просто отфильтруйте и получите.
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();
Отвечает ли это на ваш вопрос? С этой командой уже связан открытый DataReader, который необходимо сначала закрыть