Home > Software engineering >  How do I create and delete records in Entity Framework in a loop
How do I create and delete records in Entity Framework in a loop

Time:12-07

We have a postgres database to store Event objects and use Entity Framework as our ORM.

In a background service, which runs periodically, we want to get all expired events, delete them from the Event table and move them to the EventArchive table.

We have a service class ExpiredEventService which retrieves all expired events and passes them to a repository class for deletion and creating EventArchive items.

Through logging we have noticed that the expired events are indeed retrieved and that the code for deleting and creating archive item does not result in an exception.

However the items are not deleted and no EventArchive items are created.

We use the following code to move these items to the archive:

public async Task MoveEventsToArchive(IList<Event> events, CancellationToken cancellationToken)
{
    using (var dbContextTrans = _dbContext.Database.BeginTransactionAsync(IsolationLevel.ReadUncommitted, cancellationToken))
    {
        foreach(var event in events)
        {
            var archiveItem = new ArchiveEvent(event);
            archiveItem.Status = EventStatus.Archived;
            _dbContext.ArchiveEvents.Add(archiveItem);
            _dbContext.Events.Remove(event);
        }
        await _dbContext.SaveChangesAsync(cancellationToken);
    }
}

What is the correct way to do this?

CodePudding user response:

You have to commit your transaction. Also I suggest using AddRange and RemoveRange methods to improve your performance.

using (var transaction = _dbContext.Database.BeginTransactionAsync())
{
  var archives = new List<ArchiveEvent>();
  foreach(var event in events)
  {
    var archiveItem = new ArchiveEvent(event);
    archiveItem.Status = EventStatus.Archived;
    archives.Add(archiveItem);              
  }
  _dbContext.ArchiveEvents.AddRange(archives);
  _dbContext.Events.RemoveRange(events);
  await _dbContext.SaveChangesAsync();
  await transaction.CommitAsync();
}

Note: If AddRange causes PK insert problems and you can change the model, add this in your PK:

public class ArchiveEvent
{ 
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public long id { get; set; }
  //...
}
  • Related