I'm working on my first webapi in ASP.NET Core. I have two entities:
public class Event : Entity
{
private ISet<Ticket> _tickets = new HashSet<Ticket>();
public string Name { get; protected set; }
public string Description { get; protected set; }
public DateTime StartDate { get; protected set; }
public DateTime EndDate { get; protected set; }
public DateTime CreatedAt { get; protected set; }
public DateTime UpdatedAt { get; protected set; }
public IEnumerable<Ticket> Tickets => _tickets;
//.....
public void AddTickets(int amount, decimal price)
{
var seating = _tickets.Count + 1;
for (var i = 0; i < amount; i++)
{
_tickets.Add(new Ticket(this, seating, price));
seating++;
}
}
}
public class Ticket : Entity
{
public Guid EventId { get; protected set; }
public decimal Price { get; protected set; }
//... and other properties
}
When I'm trying to create new event and assign tickets to it:
public class EventController : Controller
{
[HttpPost]
public async Task<IActionResult> AddEvent([FromBody] CreateEventCommand createEventCommand)
{
createEventCommand.Id = Guid.NewGuid();
await _eventService.AddAsync(createEventCommand.Id,
createEventCommand.Name,
createEventCommand.Description,
createEventCommand.StartDate,
createEventCommand.EndDate);
await _eventService.AddTicketAsync(createEventCommand.Tickets,
createEventCommand.Price,
createEventCommand.Id);
return Created($"/events/{createEventCommand.Name}", null);
}
}
public class EventService : IEventService
{
public async Task AddAsync(Guid id, string name, string description, DateTime startDate, DateTime endDate)
{
var @event = await _eventRepository.GetAsync(id);
if(@event != null)
{
throw new Exception($"Event with this id: {@event.Id} already exist");
}
var eventToAdd = new Event(id, name, description, startDate, endDate);
await _eventRepository.AddAsync(eventToAdd);
}
public async Task AddTicketAsync(int amount, decimal price, Guid eventId)
{
var @event = await _eventRepository.GetAsync(eventId);
if (@event == null)
{
throw new Exception($"Event with this id: {@event.Id} already exist");
}
@event.AddTickets(amount, price);
await _eventRepository.UpdateAsync(@event);
}
}
public class EventRepository : IEventRepository
{
public async Task AddAsync(Event @event)
{
_context.Events.Add(@event);
await _context.SaveChangesAsync();
}
public async Task UpdateAsync(Event @event)
{
_context.Events.Update(@event);
await _context.SaveChangesAsync();
}
}
The query which is executed on Tickets table is
UPDATE [Tickets] SET [EventId] = @p700, [Price] = @p701, [PurchasedAt] = @p702, [Seating] = @p703, [UserId] = @p704, [Username] = @p705
WHERE [Id] = @p706;
SELECT @@ROWCOUNT;
After that It throws an exception:
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded.
My question is: shouldn't it be INSERT queries instead of UPDATE in this case and what could be a reason of concurrency problem in this case? I'm new to .NET and concurency in general, would be grateful for any help.
[DatabaseGenerated(DatabaseGeneratedOption.None)].