Search code examples
c#visual-studioentity-framework-coremasstransitef-core-8.0

Entity Framework core does not work when using masstransit library


I have a project, previously ef commands such as add-migration and update-database were working correctly. But I did some things after which these commands don't work anymore.

1- Adding Resharper plugin. that even by disabling this plugin, these commands still don't work. In addition, I made a test project that with this plugin, those commands worked correctly.

2- Create a new C# library. I created a folder and built the library, but instead of being built in the folder, the library was built in the root. I deleted the folder and the library and there is no trace of this library in the sln file.

3- Update all ef libraries from version 8.0.2 to 8.0.3

In my solution, there are several C# libraries, each of which has its own DbContext (cqrs). In the main project related to Command, there is a DbContext named ContentCommandDbContext, in version 8.0.2, I created another DbContext named ContentCommandDbContextFactory, which inherits from IDesignTimeDbContextFactory and fixes errors.

The problem I have now is that every ef command that I execute in the PackageManagerConsule window does not happen after the build of the project and the program remains running in the background and does not create a script. And it remains running in the background until I restart the computer.

But when I execute commands through CLI, it is done correctly.

Does anyone know where the problem is and how can I fix it so that I can use vs 2022 as before?enter image description here

-----------Update-----------

I found the problem. The problem is with the IPublishEndpoint in my custom Interceptor. When I remove the parts related to IPublishEndpoint, the commands work correctly.

Even when I create the database with CLI commands, when the program wants to save data through ef core8, the program still does not work.

 public class DomainEventsDispatcherInterceptor : SaveChangesInterceptor
{
    private readonly IMediator _mediator;
    private readonly IPublishEndpoint _publishEndpoint;
    //todo using masstransit here
    public DomainEventsDispatcherInterceptor(IServiceProvider serviceProvider)
    {
        _publishEndpoint = serviceProvider.GetRequiredService<IPublishEndpoint>();
        _mediator = serviceProvider.GetRequiredService<IMediator>();
    }

    public override async ValueTask<int> SavedChangesAsync(SaveChangesCompletedEventData eventData, int result,
        CancellationToken cancellationToken = default)
    {
        var affectedRows = await base.SavedChangesAsync(eventData, result, cancellationToken);

        if (affectedRows > 0)
        {
            var aggregateRoots =
                    eventData.Context?.ChangeTracker.Entries()
                        .Where(current => current.Entity is IAggregateRoot)
                        .Select(current => current.Entity as IAggregateRoot)
                        .ToList()
                ;

            foreach (var aggregateRoot in aggregateRoots)
            {
                // Dispatch Events!
                if (aggregateRoot != null)
                {
                    foreach (var domainEvent in aggregateRoot.DomainEvents)
                    {
                        //  await _mediator.Publish(domainEvent, cancellationToken);
                        await _publishEndpoint.Publish(domainEvent, cancellationToken); //albate domain event ehtenmalan moshkel darad bayad dar eventbus.message bashad baraye namespace ha ke dar masstransit mohem hastand
                                                                                        //add masstransit
                    }

                    // Clear Events!
                    aggregateRoot.ClearDomainEvents();
                }
            }
        }
        return affectedRows;
    }

    public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)
    {
        var affectedRows = base.SavedChanges(eventData, result);
        if (affectedRows > 0)
        {
            var aggregateRoots =
                    eventData.Context?.ChangeTracker.Entries()
                        .Where(current => current.Entity is IAggregateRoot)
                        .Select(current => current.Entity as IAggregateRoot)
                        .ToList()
                ;

            foreach (var aggregateRoot in aggregateRoots)
            {
                // Dispatch Events!
                if (aggregateRoot != null)
                {
                    foreach (var domainEvent in aggregateRoot.DomainEvents)
                    {
                        //_mediator.Publish(domainEvent);
                        _publishEndpoint.Publish(domainEvent); //albate domain event ehtenmalan moshkel darad bayad dar eventbus.message bashad baraye namespace ha ke dar masstransit mohem hastand
                    }

                    // Clear Events!
                    aggregateRoot.ClearDomainEvents();
                }
            }
        }
        return affectedRows;
    }

And the following code is the settings in the Program.cs file:

...
//add command dbcontext
builder.Services.AddDbContext<ContentCommandDbContext>((serviceProvider, options) =>
{
    options.UseSqlServer(cnn, option =>
    {
        option.EnableRetryOnFailure(6);
        option.MinBatchSize(1);
    });
    options.AddInterceptors(new IInterceptor[]
    {
        new DomainEventsDispatcherInterceptor(serviceProvider)
    }); ;
});
//add query dbcontext
builder.Services.AddDbContext<ContentQueryDbContext>(c => c.UseSqlServer(cnn));
....

builder.Services.AddMassTransit(x =>
{
    x.AddEntityFrameworkOutbox<ContentCommandDbContext>(o =>
    {
        o.QueryDelay = TimeSpan.FromSeconds(1);

        o.UseSqlServer();
        o.UseBusOutbox();
    });
    //The outbox can also be added to all consumers using a configure endpoints callback:
    // https://masstransit.io/documentation/configuration/middleware/outbox
    x.AddConfigureEndpointsCallback((context, name, cfg) =>
    {
        cfg.UseEntityFrameworkOutbox<ContentCommandDbContext>(context);
    });

    x.UsingRabbitMq((context, cfg) =>
    {
        cfg.Host("amqp://guest:guest@localhost:5672 ");
        cfg.AutoStart = true;
        cfg.ReceiveEndpoint("queue-name", c => c.ConfigureConsumers(context));
    });
    x.AddConsumers(typeof(CommentAddedEvent).Assembly, typeof(CommentAddedEventHandler).Assembly);
});
...

Can someone guide me, where is the problem?


Solution

  • I found the answer. I should have used IBus instead of IPublishEndpoint.