I have been playing with Onion Architecture, DDD and Specification pattern. There are many implementations with Entity Framework, where domain entities going right in the DBSet<> of the context. For me, it's not ok, at least because of many-to-many relationships. Let's say we have the next dbo's:
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List<PostTag> PostTags { get; set; }
}
public class Tag
{
public string TagId { get; set; }
public string Name { get; set; }
public List<PostTag> PostTags { get; set; }
}
public class PostTag
{
public int PostId { get; set; }
public Post Post { get; set; }
public string TagId { get; set; }
public Tag Tag { get; set; }
}
The problem is that entity models should not know anything about the Post.PostTag
because it's a details of implementation of the persistence layer. For instance, I could change storage to JSON objects, and it is no longer a need for an intermediate table. So, ideally, my entity models will be looking like that:
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List<Tag> Tags { get; set; }
}
public class Tag
{
public string TagId { get; set; }
public string Name { get; set; }
}
Or it goes even worse, if we decide to add some new property to PostTag
, for example
public class PostTag
{
...
public bool IsActive { get; set; }
...
}
Then, it will affect the Tag
when considering this example with entity model.
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List<Tag> Tags { get; set; }
}
public class Tag
{
public string TagId { get; set; }
public bool IsActive { get; set; } // this is added
public string Name { get; set; }
}
Because of this, I want to have both entity and dbo models.
When I implementing PostRepository, which is located at the infrastructure layer, and I want to expose the IQueriable<Post> Query()
. Here are the real problems started. The cause of problems is that the application layer, who is the consumer of the repository can operate only within the Post
entity, but not PostDbo
. And they can be different. Because of that, I can't write a specification for this entity. So, the main question is how to implement the Repository pattern which can expose such Query()
method, while having separated entity
and dbo
models, without serious effect on performance and optimality of queries.
Or, maybe, specification pattern is just a huge overhead which is more harmful then useful. The reason is that when you decide to change entity framework to something else, you should to write your own query provider for Expression<Func<TEntity>>
. What do you think?
Maybe I'm wrong with something, so correct me, please. I will be grateful for reasonable answers.
Thanks