Platinum Partner
dotnet,how-to,tools,model,mvc,net

Separating the Read Model

A typical architecture of a .NET web application is to use EF Code First for data access and MVC to render the web pages. The data model in the database is usually (and should be!) normalized. A normalized data model is also great for updates, but when displaying data it is not enough. E.g. in a table of cars I don’t want to display a numeric, database internal id of the car’s brand. I want to display the name of the brand. Creating a separate read model simplifies that.

Separating the read and write models are a key concept of the recently popular CQRS (Command Query Responsibility Separation architecture. I won’t go as far as the CQRS model does, but rather show a simple way to dress the write model’s car entity with the values required for displaying.

My key objective is to get a model where I can get everything needed for rendering a view to the user in one fetch from the database, with a minimum of extra coding and mapping code.

The Read Model

For this example I have a cars table with a foreign key (giving a navigation property) to a brands table. When displaying a list of cars I of course want to display the name of the brand, not its internal database id that’s stored in the cars table. A simple way to handle that is to wrap the car entity class in a read model (which can be used as our view model in MVC).

public class CarReadModel
{
    public Car Car { get; set; }
 
    public string BrandName { get; set; }
}

Querying for the Read Model

The purpose of the read model is to fetch everything needed to display the web page in one call to the database. That can be done with a LINQ query that projects the result into a CarReadModel object with select.

from c in ctx.Cars
where c.CarId == id
select new CarReadModel
{
    Car = c,
    BrandName = c.Brand.Name
}

The entire read model is fetched in one efficient call to the database. The read model contains everything needed for displaying.

In this case it’s perfectly fine to include the entire cars entity in the read model because the entity is so lightweight. If the entity contains any large fields (e.g. a scanned registration certificate) that is not to be displayed in all views it would be better to list the required fields explicitly in the read model instead.

Everything works fine with this code, but if the CarReadModel class is to be reused for different queries, the projection (the select part of the query) should be reusable. I’ll show a simple way to do that next week.

Published at DZone with permission of {{ articles[0].authors[0].realName }}, DZone MVB. (source)

Opinions expressed by DZone contributors are their own.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}