Wpis z mikrobloga

Cześć mirki zastanawiam się trochę na koncepcją używania Commands/Queries zamiast tradycyjnego repozytorium.
W zasadzie trafiłem na post Jimmy-ego Bogard-a, gdzie proponował podobne rozwiązanie zamiast stosowania repozytorium.

Moja interpretacja tego co on tam napisał, wygląda mniej więcej tak:

Interfejs dla queries

public interface IQueryHandler
where TResult: class
where TArg: class
{
TResult Execute(TArg query);
}

Przykładowa implementacja:

public class TreesTransQuery : IQueryHandler, TreeTransQuery>
{
private readonly DatabaseContext _context;
public TreesTransQuery(DatabaseContext context)
{
_context = context;
}
public List Execute(GetTree query)
{
return _context.Trans
.Where(x =>
_context.Trees
.Where(z => z.Id == query.TreeId)
.Union
( _context.Trees
.Where(z => z.Id == query.TreeId)
.SelectMany(z => z.Children)
).Select(z => z.Id)
.Any(q => x.Entity == $"{q}tree"))
.ToList();
}
}

Wykonanie
var result = new TreesTransQueryHandler(context).Execute(query);

gdzie query jest instancją klasy:

public class TreeTransQuery
{
public int TreeId { get; set; }
}

W sumie koncepcja nie wygląda źle. Zamiast repozytorium z 1000 linii kodu, mamy wiele obiektów, z których każdy reprezentuje konkretne zapytanie czy komendę. Komendy czy zapytania można wstrzyknąć poprzez kontener DI, a można też tworzyć je bezpośrednio korzystając z operatora new. Jak kto woli. Co wy o tym sądzicie?

#programowanie #csharp #aspnet #entityframework #aspnetmvc #wzorceprojektowe
  • 2
@pepepanpatryk: Wydaje mi się, że można to zrobić jeszcze bardziej generycznie, korzystając z _context.Set i ograniczyć użycie dodatkowych jeszcze obiektów dla każdego zapytania, jeżeli będzie ono np. takie samo dla wielu różnych encji :>
@pepepanpatryk: Przewaga Query nad Repo jest taka, że możesz w bazowej klasie zaimplementować logikię, która będzie wykonywana przed/po głównej metodzie(Execute). Czyli np. możesz tam sprawdzić uprawnienia, logować coś itd. Za to przy Repo będzie mniej kodu.