CAP is a library based on .Net standard, which is a solution to deal with distributed transactions, also has the function of EventBus, it is lightweight, easy to use, and efficiently.
The usage scenarios of CAP mainly include the following two:
You can also use the CAP as an EventBus. The CAP provides a simpler way to implement event publishing and subscriptions. You do not need to inherit or implement any interface during the process of subscription and sending.
CAP implements the publish and subscribe method of EventBus, which has all the features of EventBus. This means that you can use CAPs just like EventBus. In addition, CAP’s EventBus is highly available. What does this mean?
The CAP uses the local message table to persist the messages in the EventBus. This ensures that the messages sent by the EventBus are reliable. When the message queue fails or fails, the messages are not lost.
Use the following command to reference the CAP NuGet package:
PM> Install-Package DotNetCore.CAP
According to the different types of message queues used, different extension packages are introduced:
PM> Install-Package DotNetCore.CAP.RabbitMQ
PM> Install-Package DotNetCore.CAP.Kafka
According to the different types of databases used, different extension packages are introduced:
PM> Install-Package DotNetCore.CAP.SqlServer
PM> Install-Package DotNetCore.CAP.MySql
PM> Install-Package DotNetCore.CAP.PostgreSql
PM> Install-Package DotNetCore.CAP.MongoDB
In an ASP.NET Core program, you can configure the services used by the CAP in the Startup.cs
file ConfigureServices()
:
public void ConfigureServices(IServiceCollection services)
{
//......
services.AddDbContext<AppDbContext>(); //Options, If you are using EF as the ORM
services.AddSingleton<IMongoClient>(new MongoClient("")); //Options, If you are using MongoDB
services.AddCap(x =>
{
// If you are using EF, you need to add the configuration:
//Options, Notice: You don't need to config x.UseSqlServer(""") again! CAP can autodiscovery.
x.UseEntityFramework<AppDbContext>();
// If you are using Ado.Net, you need to add the configuration:
x.UseSqlServer("Your ConnectionStrings");
x.UseMySql("Your ConnectionStrings");
x.UsePostgreSql("Your ConnectionStrings");
// If you are using MongoDB, you need to add the configuration:
x.UseMongoDB("Your ConnectionStrings"); //MongoDB 4.0+ cluster
// If you are using RabbitMQ, you need to add the configuration:
x.UseRabbitMQ("localhost");
// If you are using Kafka, you need to add the configuration:
x.UseKafka("localhost");
});
}
Inject ICapPublisher
in your Controller, then use the ICapPublisher
to send message
public class PublishController : Controller
{
private readonly ICapPublisher _capBus;
public PublishController(ICapPublisher capPublisher)
{
_capBus = capPublisher;
}
[Route("~/adonet/transaction")]
public IActionResult AdonetWithTransaction()
{
using (var connection = new MySqlConnection(ConnectionString))
{
using (var transaction = connection.BeginTransaction(_capBus, autoCommit: true))
{
//your business logic code
_capBus.Publish("xxx.services.show.time", DateTime.Now);
}
}
return Ok();
}
[Route("~/ef/transaction")]
public IActionResult EntityFrameworkWithTransaction([FromServices]AppDbContext dbContext)
{
using (var trans = dbContext.Database.BeginTransaction(_capBus, autoCommit: true))
{
//your business logic code
_capBus.Publish("xxx.services.show.time", DateTime.Now);
}
return Ok();
}
}
In Controller Action
Add the Attribute [CapSubscribe()]
on Action to subscribe message:
public class PublishController : Controller
{
[CapSubscribe("xxx.services.show.time")]
public void CheckReceivedMessage(DateTime datetime)
{
Console.WriteLine(datetime);
}
}
In Business Logic Service
If your subscribe method is not in the Controller, the service class you need to Inheritance ICapSubscribe
:
namespace BusinessCode.Service
{
public interface ISubscriberService
{
public void CheckReceivedMessage(DateTime datetime);
}
public class SubscriberService: ISubscriberService, ICapSubscribe
{
[CapSubscribe("xxx.services.show.time")]
public void CheckReceivedMessage(DateTime datetime)
{
}
}
}
Then inject your ISubscriberService
class in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
//Note: The injection of services needs before of `services.AddCap()`
services.AddTransient<ISubscriberService,SubscriberService>();
services.AddCap(x=>
{
//...
});
}