Search code examples
entity-framework-coreblazor-server-sidecancellation

Blazor Server EF Core Cancelation


In my app I have to be able to cancel uploads, I tried with threads cancelation but nothing happens, I think it is because I use DBContextFactory and I create a context for each uploaded file.

So I did this to save files in DB:

    private async Task OnFilesDropped(FileUploadModel upload)
    {
        Uploads.Add(upload);
                           
        if (string.IsNullOrEmpty(upload.Error))
        {                                
            using var context = DbFactory.CreateDbContext();

            upload.Context = context;

            context.FileUploads.Add(upload);

            upload.UploadCompletion = 45;

            await context.SaveChangesAsync();

            upload.UploadCompletion = 100;                                                                         
        }                        
    } 

and this in case of deleting a uploaded/uploading file:

    private async Task DeleteUpload(FileUploadModel upload)
    {
        Uploads.Remove(upload);

        await UploadsChanged.InvokeAsync(Uploads);

        if (string.IsNullOrEmpty(upload.Error))
        {
            if (upload.UploadCompletion != 100)
            {
                await upload.Context.DisposeAsync();
            }
            else
            {
                using var context = DbFactory.CreateDbContext();

                context.FileUploads.Remove(upload);

                await context.SaveChangesAsync();
            }                
        }
        
    }

This way works because I dispose of the context, but I wonder if there is a better way of doing this? or if this solution could be problematic somehow?

Best Regards.


Solution

  • You should use a CancellationToken.

    The SaveChangesAsync method on your context has an overload that can be provided a cancellationToken.

    await context.SaveChangesAsync(cancellationToken);
    

    If you already have a CancellationToken higher in the call stack, you can just pass that one down. Otherwise, you can create a CancellationTokenSource and use that to generate a cancellation token and then cancel it when appropriate.