未加星标

Getting Started with CQRS Part 2

字体大小 | |
[数据库(综合) 所属分类 数据库(综合) | 发布者 店小二05 | 时间 2019 | 作者 红领巾 ] 0人收藏点击收藏
The series so far: Getting Started with CQRS Part 1

The first article of the series dove into the main concepts of CQRS along with the project configuration and setup. You learned how to create a basic CRUD-like application with ASP.NET and integrate it with a simple data source structure that relies on the Entity Framework and SQLite.

It’s important to notice, until here, that no CQRS concept was applied yet, since the whole implementation is about CRUD operations. This is intentional, for you to better understand how this pattern can apply in existing REST applications as well as web and even desktop applications that want to take advantage of it.

For the second part of the tutorial, you’ll finish the CQRS configurations by creating the MongoDB code, which is going to be responsible for the query side of the pattern. Also, you are going to create the commands that will operate over the creation and update of the data through normal relational database operations; finish the customer controller, which, in turn, will access the commands and queries to serve each appropriate endpoint; and, finally, set up the event-driven architecture with RabbitMQ for the publishing and subscribing of all the events the application has to deal with.

Creating the Query Side

Start by creating the MongoDB configurations, necessary for the Query side of the CQRS model. Open the CustomerAPI application in Visual you created in the first article and open your Startup.cs class. (You can find the code for this article here .) Add another transient repository setting, right below the SQLite one:

services.AddTransient<CustomerMongoRepository>();

Don’t forget the proper using statement at the beginning of the file:

using CustomerApi.Models.Mongo;

Add a new folder to the project: \Models\Mongo . Create a new class, CustomerMongoRepository in the new folder. This new class will accommodate the same CRUD operations you’ve created in the SQLite repository. However, using the specific configurations provided by the previously imported Mongo driver library. Replace the code:

using System.Collections.Generic; using MongoDB.Driver; namespace CustomerApi.Models.Mongo { public class CustomerMongoRepository { private const string _customerDB = "CustomerDB"; private const string _customerCollection = "Customers"; private IMongoDatabase _db; public CustomerMongoRepository() { MongoClient _client = new MongoClient("mongodb://localhost:27017"); _db = _client.GetDatabase(_customerDB); } public List<CustomerEntity> GetCustomers() { return _db.GetCollection<CustomerEntity>(_customerCollection).Find(_ => true).ToList(); } public CustomerEntity GetCustomer(long id) { return _db.GetCollection<CustomerEntity>(_customerCollection).Find(customer => customer.Id == id).SingleOrDefault(); } public CustomerEntity GetCustomerByEmail(string email) { return _db.GetCollection<CustomerEntity>(_customerCollection).Find(customer => customer.Email == email).Single(); } public void Create(CustomerEntity customer) { _db.GetCollection<CustomerEntity>(_customerCollection).InsertOne(customer); } public void Update(CustomerEntity customer) { var filter = Builders<CustomerEntity>.Filter.Where(_ => _.Id == customer.Id); _db.GetCollection<CustomerEntity>(_customerCollection).ReplaceOne(filter, customer); } public void Remove(long id) { var filter = Builders<CustomerEntity>.Filter.Where(_ => _.Id == id); var operation = _db.GetCollection<CustomerEntity>(_customerCollection).DeleteOne(filter); } } }

Notice that, this time, you have more operations for retrieving/searching elements from the database than in the SQLite repository. It happens because, as the Query side of the model, some flexibilities like searching by the id or email must exist in order to accommodate the different types of searches the client may perform.

The other operations will help with tests, like creating, updating and removing items from the database for checking purposes.

Also, it’s important to attain to the name of the database and the collection ( _customerDB and _customerCollection , respectively). They must be exactly the same as the ones you created before at MongoDB Compass in the previous article. Thanks to the lambda functionalities .NET provides, you can pass summarized functions as arguments to most of the methods of MongoDB database.

Next, it’s time to create the Mongo entities, mapping exactly the same values to expose to the clients, in response to the values saved in the SQLite entities. Inside the \Mongo folder, create a new class called CustomerEntity.cs and add the following code:

using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; using System.Collections.Generic; namespace CustomerApi.Models.Mongo { public class CustomerEntity { [BsonElement("Id")] public long Id { get; set; } [BsonElement("Email")] public string Email { get; set; } [BsonElement("Name")] public string Name { get; set; } [BsonElement("Age")] public int Age { get; set; } [BsonElement("Phones")] public List<PhoneEntity> Phones { get; set; } } }

The class is basically composed of the same properties found in the corresponding SQLite code. The annotation BsonElement is provided by the MongoDB library and specifies the element name of each field of the entity. This is important, because this is how Mongo will identify each field when saving the document-based values to the database through a key-value system. Add another class to folder, PhoneEntity .

Here is the code for PhoneEntity.cs :

using MongoDB.Bson.Serialization.Attributes; namespace CustomerApi.Models.Mongo { public partial class PhoneEntity { [BsonElement("Type")] public PhoneType Type { get; set; } [BsonElement("AreaCode")] public int AreaCode { get; set; } [BsonElement("Number")] public int Number { get; set; } } }

Both SQLite and MongoDB use the same PhoneType.cs class from the previous article. Make sure that it is in the \Models folder.

Setting up the Event Handler

In order for RabbitMQ to work in an ASP.NET project, besides having a proper RabbitMQ client dependency configured on the project, it’s also necessary to register the publisher and the subscriber beans in the Startup.cs class ( ConfigureServices() method):

services.AddTransient<AMQPEventPublisher>(); services.AddSingleton<CustomerMessageListener>();

Don’t forget to import the proper using statements at the beginning of the class.

using CustomerApi.Models.Mongo;

Start with the publisher by creating a new \Events folder on the root folder. Then, create a class called AMQPEventPublisher.cs and add the following code:

using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using RabbitMQ.Client; using System.Text; namespace CustomerApi.Events { public class AMQPEventPublisher { private readonly ConnectionFactory connectionFactory; public AMQPEventPublisher(IHostingEnvironment env) { connectionFactory = new ConnectionFactory(); var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json"

本文数据库(综合)相关术语:系统安全软件

代码区博客精选文章
分页:12
转载请注明
本文标题:Getting Started with CQRS Part 2
本站链接:https://www.codesec.net/view/627902.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(综合) | 评论(0) | 阅读(96)