The best way to create Read Model (aggregate) - c#

I have to create a complex "read model" (cart) with CartLine and some other informations. At the moment I have a ViewModel based on many other objects (Cart, Operation...), the logic to build this object is dispatched in a Respository and a Controller (not in Aggregate), and I want refactor this code, with the repository to return directly the "read model" (With formatted text, price...).
I am only allowed to use Stored Procedure (client's policy) with Dapper. I am looking for a better way to create this read model :
1.Call existing stored procedures, map the stored proc results on DTO and then map again the results on my read model
public class Cart
{
public Cart(CartDb cartDb, IEnumerable<CartDetailDb> cartDetailsDb,
OperationDB operationDb)
{
//Code
}
}
-> Have two levels of objects, I think it's a mess
2.Create stored procedures that will map directly to my read model (to avoid the DTOs)
-> I don't like this method because I could end up putting some logic in the Stored Procedures
3.Use ViewModel
Other suggestions?

If I understand you correctly, your data model for this entity does not exactly line up with your domain model for this Read entity. You would also like your repository layer to return you the domain model version of Read directly without requiring some intermediary DTO layer.
In my opinion, option #1 makes the most sense. Because there is an impedance mismatch between your data model and domain model, mapping logic will be required somewhere to translate data between the two models. The most appropriate place for this logic to go would be inside of your repository layer, since the entire purpose of this layer is to map objects between the domain and their persistence.
This does not mean that you need to create a DTO layer to map from your stored procedure that you just then turn around and remap to a domain object. You could simply perform the translation logic directly on the result sets returned by your data access layer and turn it into a domain object in one step.
In the case of data access, the need for DTOs is largely determined by what technology you are using for data access. For example, if you are using the ADO.net libraries (SqlCommand, SqlConnection, etc) then a DTO is probably not required. However, if you're using an ORM like Entity Framework or NHibernate then it may make sense to use the objects generated by those tools strictly as a DTO and map to a full fledged domain object. Of course, since those objects are generated for you that pretty much eliminates any maintenance issues with having a DTO layer.
This also does not mean that you need to place the translation logic in your stored procedures in order to make the data layer return result sets that exactly match your domain model. I would avoid this at all costs as you said yourself, this puts domain logic in your database.
Finally, you mention that the domain object consists of "Formatted Text" such as price. I would point out that most times text formatting is actually part of the UI layer and not your domain model. That means that if you have a property on your model such as Price, it should be represented as a Double or Decimal and not a String formatted as currency. In other words, the value should be 5.00 and not "$5.00".
For handling formatting translations like these, it's appropriate to wrap your domain object with a ViewModel like you mentioned, to handle the translation from the domain to the UI layer. Using a strict separation concerns in situations like these helps to create a more robust system that is easier to maintain.

Related

interaction between data data acess layer and business layer

i'm beginner in repository and layerd application and i don't inderstand well which is the interaction and the relationship between the repositories and business layer classes
Here is an example for purchaese order in 3 layers and I want to review whether correct or not and your correction
for DataAcesslayer
repository OrderRepositolry
Namespece Dal
{
       Public class RepositoryOrder
       {
              POrderContext context = new POrderContext ();
 
              Public IEnumrebale <Order> GetAll ()
              {
                   Context.Orders;
              }
// Following code
       }
}
for the item of order repositories code :
namespece Dal
{
public class RepositoryOrderItem
{
POrderContext context = new POrderContext();
public IEnumrebale<OrderItem> GetAllItemById(Order o)
{
context.OrderItems.where(i => i.OrderId == o.Id);
}
public OrderItem GetItemById(int id)
{
context.OrderItems.Find(id);
}
//Following code
}
}
for businessLayer here is classOrderBLL code:
namespace BLL
{
public class OrderBLL
{
RepositoryOrder repoOrder = new RepositoryOrder();
RepositoryOrderItem repoItem = new RepositoryOrderItem();
public IList<Order> GetAll()
{
return repoOrder.GetAll();
}
public decimal GetPrixTotal(Order order)
{
var query = from item in repoItem.GetAllItemById(order)
select sum(item=>item.Prix * item.Quantite);
return query;
}
}
}
does the total price calculation is done at the level of repository
or at the level of BLL (we can make this request linq with context
in the repository)?
CRUD method is done at repository and they are called at BLL from
repository is it right?
does the where method in linq corresponds to logical business or
repository (data access layer) since it determines certain rules in
the business?
I'm sure this question will be voted down as "primarily opinion based" but before that happens I'll jump in to give my "primarily opinion based" answer :-)
There are two ways to partition a database application and they depend on how complex and large it will be. Entity Framework examples tend to give a very simplistic model, where the EF Data classes are exposed to the Business layer which then exposes them to the View Model or other layers. This may be correct for simplistic applications but for more complex ones, and ones where the data storage method is not RDBMS (i.e. No-SQL) or where you want to create separation between business and repository data structures it is too simple.
The repository layer should have a set of classes which describe how the data is accessed from the repository. If you have an RDBMS these might be EF POCO classes, but if you have a web-service endpoint as your repository this may be SOAP documents, or REST structures, or other Data Transfer Object. For an RDMBS like SQL Server that uses exclusively stored procedures for accessing its data, the Repository layer might simply be a set of classes which mirror the naming and parameters, and data sets returned by the stored procedures. Note that the data stuctures returned by anything other than an RDBMS might not be coherent - i.e. a "Customer" concept returned by one method call in the repository might be a different data structure to a "Customer" returned by a different call. In this case the repository classes would not suit EF.
Moving to the business object layer - this is where you create a model of the business domain, using data classes, validation classes and process class models. For instance a Process class for recording a sales order might combine a Business Customer, Business Sales Order, Business Product Catalog data concepts and tie in a number of Validation classes to form a single atomic business process. These classes might (if you are doing a very lightweight application) be similar to data at the Repository layer but they should be defined seperately. Its in this layer you hold calculated concepts such as "Sales Order Total" or "VAT Calculation" or "Shipping Cost". They might, or might not, get stored into your Repository but the definition of what they mean are modelled in the business layer.
The business layer provides the classes whose data is copied across into a View Model. These classes again can be very similar (and in the simplest of cases, identical to) the repository classes, but in their job is to model the user interface and user interaction. They might contain only some of the data from the business data classes, depending on the requirements of the UI. These classes should carry out user interface based validation, which they might delegate to the business tier, or might add additional validation to. The job of these classes is to manage the state-machine that is the user interface.
My summary is that in a large scale system you have three sets of classes; data repository interaction, business model interaction, and user interface interaction. Only in the simplest of systems are they modelled as a single set of physical POCO classes.

Building applications using multiple datasources for single objects

I'm struggling finding a right solution for my application architecture. For my application I have a single class for customers. The data for filling my customer objects are spread over multiple different types of datasources. The main part is exposed in a readonly Oracle database, other parts are exposed using a webservices and I need te save some extra data to another datasource (for instance a MS SQL database using entityframework) since I only have readonly rights for most datasouces (they are managed somewhere else).
For this reason I wanna build some kind of central library with connectors to all of my datasources for creating a centralized Customer Object to work with. So far so good for this idea (I think) but I can't find any documentation or example with best practices how to achieve such a solution.
EXAMPLE:
* Main Application (multiple applications)
- Central Business Logic Layer (Business-API)
* Webservice Connector
* Oracle Connector
* EntityFramework Connector
Does anyone know if there is some good reading material on this specific subject?
Kind regards
The specific problem you describe with customer objects sounds a lot like the one solved by the Data Mapper pattern, which is technically a kind of Mediator. Quoting from the Wikipedia page for Data Mapper:
A Data Mapper is a Data Access Layer that performs bidirectional transfer of data between a persistent data store (often a relational database) and an in memory data representation (the domain layer). The goal of the pattern is to keep the in memory representation and the persistent data store independent of each other and the data mapper itself. The layer is composed of one or more mappers (or Data Access Objects), performing the data transfer. Mapper implementations vary in scope. Generic mappers will handle many different domain entity types, dedicated mappers will handle one or a few.
Although the language of the problem above speaks of a persistent data store that's singular, there's no reason why it couldn't be several data locations (Mediator pattern hides the details from the collaborators).
There is an extension of this pattern, known as the Repository pattern:
I suggest the DAO-Pattern to abstract from any data access. The business logic should not be aware of any datasources. This is the most important aim. Anything else has to be subordinated.
You can create a constructor that accepts datasources like:
public class Customer
{
public Customer(OracleConnector oracle, WebSerivceConnector webservice, EntityConnector entity)
{
this.oracle = oracle;
this.webservice = webservice;
this.entity = entity;
}
public void Fetch()
{
// fetch data from oracle, webservice, and entity.
this.Name = oracle.GetCustomerName();
}
}
This way only Customer knows how to get the data, all the logic is in one place. You can even make it more testable and less coupling by creating interfaces for connectors.
public interface IOracleConnector
{
// add something here
string GetCustomerName();
}
public class OracleConnector
: IOracleConnector
{
// add the implementation here.
}
Then change Customer constructor to accepts IOracleConnector like:
public Customer(IOracleConnector oracle, WebSerivceConnector webservice, EntityConnector entity)
{
// your code here.
}
Now, you can create a mock to test Customer without actually connecting to the database.

Where to load the data to fill a viewmodel with more than one poco class

i have to show an object (a POCO class) in a form.
In my controller, i get the objects data from the objects repository.
But in the form, i have to show some extra data about the object as well, like the country name and not the countryid, the number of persons assigned (to fetch from a 1:N relation), the history of edits (to fetch from yet another table) and the bit 'CanBeCancelled'.
The question is: where should i put this logic?
I came up with these alternatives:
The repository itself: create an extra function which returns this
exact viewmodel
a conversionservice, which converts the class to the
viewmodel (it knows where to get the data)
the controller: it knows
what data to show in the view(model), so it should get all the data
from the different repositories
What is a good way to place this logic (with 'this logic' i mean the logic to know that the number of persons is fetched in repository A, the history is fetched by repository B and the countryname is fetched by the CountryRepository and the boolean 'CanBeCancelled' is fetched by the StateEngine service) ?
If there are no other constraints, I would follow simple rule stated by Single Responsibility Principle - each layer should do its own job and presume that other layers do their job properly. In this case repositories return the business object, services process the business object and the controller only knows how to display the object properly. In details:
Number of persons, history and country name are already in the storage, and should come from there. So repository should return a complete object - as long as the operations are about the same entity.
When several entities are involved in the process, service is responsible for calling corresponding repositories and constructing an object.
Things that are figured out according to the business rules are the job for service object as well.
Controller receives complete object by calling single method of a service and displays it
Benefits of this approach will be evident once you decide to change something, say business rule about how the object is allowed to be cancelled. This has nothing to do with access to the database, and does not involve application UI, so the only place you want to change in this case is service implementation. This approach allows you to do just that, without need to alter code of repositories and controllers.

My entities have only setters and getters but no methods - design failure -

I have read this once:
"Don't leave entities as bags of getters and setters and put their methods in another layer unless you have a good reason to"
My customer, order, ... objects just get the data from the SqlDataReaders. They have only getter and setter.
My first question is which design approach does this follow when someone implements methods in entities AND what are these methods doing?
This way of thinking comes from the Domain Driven Design community.
In DDD you create a Domain Model that captures the functionality that your users request. You design your entities as having functionality and the data they need for it. You group them together in aggregates and you have separate classes that are responsible for construction (Factories) and querying (Repositories).
If you only have getters/setters you have an 'Anemic Domain Model'. Martin Fowler wrote about it in this article.
The problem with an Anemic Domain model is that you have the overhead of mapping your database to objects but not the benefits of it. If you don't use your entities as a real domain model, why don't you just use a DataTable or something for your data and keep your business logic in separate functions? An Anemic Domain model is an anti-pattern that should be avoided.
You also mention that you map the entities yourself. This blog explains why using an Object-Relational Mapping tool can really help. If you use Entity Framework with a Code First approach you can write a clean domain model with both data and functionality and map it to your database without much hassle. Then you will have the best of both worlds.
When you have methods as part of your model, you should only include model specific type of logic. For example, consider a bank account:
public class Account {
public AccountId Id { get; set; }
public Person Customer {get; set; }
public void Credit(Money amount) { ... }
public void Debit(Money amount) { ... }
}
Credit and Debit are model-specific logic (you won't find them anywhere else in the application), and should be encapsulated in the Account class.
You also mentioned that you used SqlDataReader within your model classes to get the data from the database. This is a big anti-pattern. Here are some problems you will encounter with this:
Violating Single Responsibility Principle - The model is now in-charge of representing the data and getting the data from the db.
How about querying children in your model? It gets messy.
You won't be able to change your data-access as easily.
Keep the model lean. Put the data access logic in a repository, i.e. AccountRepository.

How to create a business model wrapper for a generic database approach?

I'm currently facing a performance problem with creating POCO objects from my database. I'm using Entity Framework 4 as OR-Mapper.
The whole application is a prototype for now.
Let's assume I want to have some business objects like classes 'Printer' or 'Scanner'. Both classes inherit from a BaseClass called Product.
The business classes exist.
I try to use a more generic database approach. I don't want to create tables for "Printer" nor "Scanner". I want to have 3 tables: One called Product, and the other Property and PropertyValue (which stores all assigned values to a specific Product).
In my business layer I do create a specific object like this:
public Printer GetPrinter(int IDProduct)
{
Printer item = new Printer();
// get the product object with EF
// get all PropertyValues
// (with Reflection) foreach property in item.GetType().GetProperties
// {
// property.SetValue("specific value")
// }
return item;
}
This is how the EF model looks like:
Works fine so far. For now I'm doing performance tests for retrieving multiple sets.
I've created a prototype and improved it several times to increase the performance. It is still far away from being usable.
I takes 919ms to create 300 objects who only contain 3 properties.
The reason for choosing such DB design is to have a generic database design. Adding new properties should only be done in the business model.
Am I just being too stupid to create a performant way of retrieving xx objects or is my approach totally wrong? As far as I understand OR-Mapper, they are basically doing the same?
I think you missed whole point of ORM. The reason why people are using ORM is to be able to persist buisness objects and easily retrieve business objects. You are using ORM to get just data for your business objects' factories. Factories are using reflection to build business object from materialized classes retrieved by ORM. This will always be very slow because:
Query compilation is slow (you can precompile it)
Object materialization is slow (you can't avoid it)
Reflection is slow (you can't avoid it)
IMO if you want to follwo this DB design to have generic tables absolutely independent on your business objects you don't need ORM or at least you don't need EF.
The reason for your performance problems is that generic approach is not follwed in your business model. So you must somewhere convert generic data to specific data = slow operation.
If you want to improve performance define set of shared properties and place them into Product. Then either use your current PropertyValue and Property for additional non shared properties or use simply ExtendedProperties table storing key value pairs. Your entities will be of type Product with inner type property, shared properties and collection of extended properties. That is generic approach.
Firstly, it's not clear to me what you have in the way of POCOs. Did you hand code these and your context or T4 generate them? There are some great articles here that benchmark performance with no POCO, T4 Generated POCOs/Context and hand coded POCOs/Context. As expected there is HUGE performance savings going with POCOs (more than a 15-fold boost in performance in his benchmark) going the POCO route over those generated by the Entity Framework. You don't say what DBMS...if MSSQL have you turned on the profiler and see what's being generated?

Categories

Resources