2

I am here to ask question about:

  • is it good practice to insert many records using CQRS and MediatR?
  • how to structure that in terms of names and folders?

A have to insert into database over 500 records and now I am doing it like this:

foreach (var item in list)
{
    var command = new CreateItemCommand() 
    {
        Name = "Adam",
        Job = "Support"
    }

    await _mediator.Send(command);
}

This is obviously an example, my object's are much bigger. The problem is that, it takes around 15 seconds to insert 500 records..

If I could do something like this:

var list = new List<Person>();

foreach (var item in persons)
{
    list.Add(new Person() 
    {
        Name = "Adam",
        Job = "Support"
    });
}

var command = new CreateManyItemsCommand() 
{
    List = list
}
await _mediator.Send(command);

The same operation will be much faster.

So, let me back to questions:

  • is it good practise?

  • Structure: db/Commands/CreateManyItems/CreateManyItemsCommand.cs or db/Commands/CreateItem/CreateManyItemsCommand.cs ?

Please, share some thoughts on this :)

If anyone wondering how my current handler looks, here it is:


public class CreateItemCommand : IRequest<int>, IMapFrom<Item>
{
    public string Name { get; set; }
    public string Job { get; set; }
}

public class CreateItemCommandHandler : IRequestHandler<CreateItemCommand, int>
{
    private readonly IMapper _mapper;
    private readonly IDbContext _context;

    public CreateItemCommandHandler(IDbContext context, IMapper mapper)
    {
        _mapper = mapper;
        _context = context;
    }

    public async Task<int> Handle(CreateItemCommand request, CancellationToken cancellationToken)
    {
        var entity = _mapper.Map<Item>(request);

        _context.Items.Add(entity);

        await _context.SaveChangesAsync(cancellationToken);

        return entity.Id;
    }
}

1
  • 2
    Instead of CreateManyItems you might want to use the term BatchCreateItems. It conveys the same information, and batch processing is indeed a valid strategy for creating several items at once. Commented Oct 14, 2021 at 14:31

2 Answers 2

1

is it good practice to insert many records using CQRS and MediatR?

Absolutely. There's nothing wrong on that. In fact, start chaining calls to the mediatr is considered an anti-pattern by many.

Structure: db/Commands/CreateManyItems/CreateManyItemsCommand.cs or db/Commands/CreateItem/CreateManyItemsCommand.cs ?

Yes, altough this is a opinion-based concern. I typically add both the IRequest and the IHandler in the same file, and simply call it "CreateManyItems.cs". Regarding the path, I tend to prefer "UseCases/Items/Commands/CreateManyItems.cs" As your operation seems to be on a one-by-one basis in terms of transactions, I would avoid using the term "batch" altogether.

1
  • 1
    Chainging calls is an anti pattern you say. I am curious for some sources and reasons. I do not disagree; i just want to learn more about this perspective! Commented Dec 14, 2021 at 18:37
0

Another approach you could use is instead of awaiting each task seperately, sending them all at once.

var tasks = list.Select(x => _mediator.Send(new CreateItemCommand { /* stuff */ })).ToList();

await Task.WhenAll(tasks);

This sends all the tasks in one go, optimizing speed. But you might introduce issues at other points like opening 50 database connections at the same time, so you will have to handle these problems now too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.