DDD / CQRS: Consolidation of reading models for user interface requirements

Let’s use the classic blog context example. In our domain we have the following scenarios: Userscan write Posts. Postsmust be cataloged in at least one Category. Postscan be described using Tags. Userscan comment Posts.

Four sites ( Post, Category, Tag, Comment) are implemented as separate units because of the fact that I did not find any rule to the data entities intervened in the other. So, for each aggregate, I will have one repository that represents it. In addition, each population refers to others by its identifier.

Following CQRS, this script I read typical use cases that lead to commands such as WriteNewPostCommand, PublishPostCommand, DeletePostCommand, etc. along with their respective queries for retrieving data from repositories. FindPostByIdQuery, FindTagByTagNameQuery, FindPostsByAuthorIdQueryEtc.

Depending on which site of the application we are on (backend or front), we will have more or less complex requests. So, if we are on the first page, we may need to create some widgets in order to receive the latest comments, the last message of the category, etc. Queries that include a simple object Query(several search criteria) and QueryHandlervery simple (one repository as a dependency on the handler class)

But elsewhere, these queries may be more complex. In the admin panel, we need to show in the table a relationship that satisfies complex search criteria. There may be interesting search messages: author’s name (without identifier), category names, tag name, publication date ... A criterion that applies to different aggregates and different repositories.

In addition, in our message table, we do not want to display the message along with the author ID or category identifier. We need to show all the information (username, avatar, category name, category icon, etc.).

My questions:

  • , , (findAll, findById, findByCriterias...) , ? , a findPostById(uuid) findPostByCustomFilter(filter), post , , , ? - , , ?

  • , 12/12/2014, , "" "" "sci-fi" "adventure", , Query QueryHandler?

a) Query (authorName, categoriesNames, TagsNames, User, Category, Tag ), QueryHandler . ...

b) Queries (FindCategoryByName, FindTagByName, FindUserByName), - FindPostQuery, authorid, categoryid, tagid, ?

b) , .

+4
2
  • . , . , () , . , , .

  • " " - SearchCriteria. , Query, , , .

+3

CQRS . , , dll .

a) QueryModel, , . Entity Framework NHibernate, togheter, DbContext Session.

b) , , , ORM, , , IQueryable LET ( Linq), .

Entity Framework # :

public class QueryModelDatabase : DbContext, IQueryModelDatabase
{
    public QueryModelDatabase() : base("dbname")
    {
        _products = base.Set<Product>();
        _orders = base.Set<Order>();
    }

    private readonly DbSet<Order> _orders = null;
    private readonly DbSet<Product> _products = null;

    public IQueryable<Order> Orders
    {
        get { return this._orders.Include("Items").Include("Items.Product"); }
    }

    public IQueryable<Product> Products
    {
        get { return _products; }
    }
}

, , -:

using (var db = new QueryModelDatabase())
{
    var queryable = from o in db.Orders.Include(p => p.Items).Include("Details.Product")
                    where o.OrderId == orderId
                    select new OrderFoundViewModel
                    {
                        Id = o.OrderId,
                        State = o.State.ToString(),
                        Total = o.Total,
                        OrderDate = o.Date,
                        Details = o.Items
                    };
    try
    {
        var o = queryable.First();
        return o;
    }
    catch (InvalidOperationException)
    {
        return new OrderFoundViewModel();
    }
}
+1

Source: https://habr.com/ru/post/1614441/


All Articles