Modelling a directed graph in EF CF - c#

I'm having some trouble using EF Code First to model a graph structure. I have a situation whereby numerous concrete objects within my application can be nodes that relate on any of a number of types of edge.
For example, two User objects may have a relationship (like, dislike, related to), but each could equally relate to another type of object ('viewed' page, 'liked' message etc.)
To model this within the application I'm using a base class of GraphNode from which all of the possible nodes will inherit, and each GraphNode has a collection of Edges. Each Edge has a SourceNode, a DestinationNode and a RelationshipType (used for weighting).
I know how I would model this as a straight Database-first development, with a table for Edge that would have a surrogate key, SourceObjectID and DestinationObjectID fields which would be the PKs from the objects being linked, SourceObjectType and DestinationObjectType fields which are the type of object being related, but the site requires EF Code First implementation.
I've got it to a point where I'm using TPT inheritance, so I've got a GraphNode table with a PK that's the GraphNodeID, but it's then using this as the PK for each of the tables for the concrete types, in place of their own PKs which is going to cause problems.
Has anyone done this, or can anyone point me in the right direction for a way to do this?

As you've found out, inheritance is not a great fit for this scenario.
Other ORMs, like NHibernate, provide out-of-the-box support for "heterogeneous associations". Since EF does not, my solution is to handle this at the "service" layer (i.e. between the controllers/viewmodels and the DbContext).
What I do is create an abstraction that lets me store and retrieve elements (in my case, Notes or Comments) associated to any entity. I do that by manually storing the entity type and id of the referenced object.
This is mostly trivial except when you want to associate the elements with a non-yet-persistent entity (I handle that using some callbacks in my DbContext)

Related

DDD and references between aggregates in EFCore and C#

I have an issue that I am not sure how to solve when DDD is assumed and using C#/EF Core.
Simplified situation: We have 2 aggregates - Item and Warehouse. Each of them has its identity by ExternalId(Guid) to identify it outside (FE etc) which is also treated as its domain identity. It also has database Id that identifies it inside databases model - Entity model and Db model is the same class as EF Core allows to use private fields - only the ExternalId, and required fields are exposed. Entity (both in DDD and EF Core sense) contain quite a lot of business logic and methods strictly coupled to the object. In general I follow the pattern from eShop/eShopOnContainers example.
Item is assigned to Warehouse and when creating an item we need to pass Warehouse to its constructor.
Is it proper to pass full Warehouse object to Item's constructor (but also to other methods that Item defines):
public Item(Warehouse warehouse,..)
or should I relay on database Id only :
public Item(long warehouseId,..)
I have an issue about this, because from one one side I read that aggregates should not reference other aggregates, but on the other hand using Datbase DB leaks the implementation detail (object persitsance in relational DB) to domain model which should not happen in my opinion.
Using ExternalId:
public Item(Guid warehouseId,..)
does not solve the problem as actual relations in db do not base on it.
What is your opinion ? I am a bit puzzled.
Usually you would create a Value Object for the Id of the Aggregate Root. It is one possibility to rely on a Id generated by the database. If you decide to let the Db generate the Id, then you will need to work with that.
But why would you need to pass the Warehouse reference or Id anyways? It looks like Item is an Entity and Warehouse is the Aggregate Root that should contain that Entity. In general you should not create an Entity outside of the Aggregate Root.
Edit: There are several identity creation strategies as Vaughn Vernon describes in the red book. One of them is let the persistance mechanism such as a SQL Db generate the unique identifier of an entity or aggregate.
Your domain model created during analysis is often different from the one created during design. Semantically they are both the same, you are passing references, but the design model recognises that you have to persist the data so you might not want to pre-load all referenced objects for performance reasons, whether that is simply loading it from disk within the same domain, or from a remote service in another domain.

EntityFramework (ORM) object names and domain model names - how to avoid duplicates?

Let's say I have a project where I use Entity Framework, but I want to use my own classes instead of the EF classes.
Reasons for using my own classes:
Easy to add properties in code
Easy to derive and inherit
Less binding to the database
Now, my database has table names like User and Conference.
However, In my domain project, I also call my files User.cs and Conference.cs.
That means I suddenly have two objects with the same naming, which is usually very annoying to work with, because you have to use namespaces all the time to know the difference.
My question is how to solve this problem?
My ideas:
Prefix all database tables with 'db'. I usually do this, but in this case, I cannot change the database
Prefix or postfix all C# classes with "Poco" or something similar
I just don't like any of my ideas.
How do you usually do this?
It's difficult to tell without more background but it sounds like you are using the Entity Framework designer to generate EF classes. This is known as the "Model First" workflow. Have you considered using the Code First / Code Only workflow? When doing code first you can have POCO classes that have no knowledge of the database, EF, or data annotations. The mapping between the database and your POCOs can be done externally in the the DBContext or in EntityTypeConfiguration classes.
You should be able to achieve your goal of decoupling from EF with just one set of objects via code first.
To extend the above answer, the database table name User (or Users as many DB designers prefer) is the identifier for the persistence store for the object User that's defined in your code file User.cs. None of these identifiers share the same space, so there should be no confusion. Indeed, they are named similarly to create a loose coupling across spaces (data store, code, development environment) so you can maintain sanity and others can read your code.

Can NHibernate QueryOver load DTO's with associations?

I have an entity (A) with an association (B) and I want to load and transform all of those in DTO's (with less fields than their corresponding entities). So I want a similar structure of ADto's, each with an associated BDto. Can you do that with one query (preferably QueryOver-style)? Also it would be ideal if the BDto's are reused if the represent the same entity.
I usually do this for a single entity with ISession.QueryOver<...>().SelectList(...); but don't know if this works for associations as well.
If you need associations in your DTOs, you have to manually provide them. Possibly this link could give you some ideas:
http://netpl.blogspot.com/2010/12/generic-dto-model-and-other-silverlight.html
Basically, the idea is to have a generic wapper-model for your DTOs so you'd put both ADtos and BDtos there, however because of the way the model is created (a set of dictionaries) it's easy to cross reference dtos.
This doesn't have anything in common with NHibernate though, the idea is more general.

Exposing derived types via data service for OData queries

I have created an EF4 CTP5 based code first model that includes two entities in a parent-child relationship where the child entity contains several extra fields. Both types are derived from the same table TPH and use a newly created discriminator. Now, I need to figure out how to expose the child entityset via the data service and make it available for querying.
The use-case for this is that we have a table that contains a hierarchy of clients. Each client has a parent and zero or more children. A parent contains just the information needed to set-up the client and for billing (name, address, etc.). The children (you can think of them as sattelite branches) contain an additional set of properties that are unique to them in addition to what they inherit from the parent. All are contained in the same table that has been denormalized for pure search performance.
So far, I have exposed the entity set in the manner suggested in this blog post It suggests exposing a method that returns the context.Child IQueryable collection. However, this entity set is way too large (700k+ records) to just expose the entire thing and I cannot seem to get standard oData queries to work against the service operation.
My questions are numerous but to keep this post as concise as possible I will limit them.
•First, I want to know if this is still the best and only way to handle this? It seems like not allowing derived types to be exposed without this workaround is a major gap in functionality.
•Second, how can I query this entityset? Is this possible? Is it possible I do not have something materialized properly in the EF piece?
Any and all help or suggestions are greatly appreciated.
Best and thanks in advance!

Application Design - Database Tables and Interfaces

I have a database with tables for each entity in the system. e.g. PersonTable has columns PersonId, Name, HomeStateId. There is also a table for 'reference data' (i.e. states, countries, all currencies, etc.) data that will be used to fill drop down list boxes. This reference table will also be used so that PersonTable's HomeStateId will be a foreign key to the reference table.
In the C# application we have interfaces and classes defined for the entity.
e.g. PersonImplementationClass : IPersonInterface. The reason for having the interfaces for each entity is because the actual entity class will store data differently depending on a 3rd party product that may change.
The question is, should the interface have properties for Name, HomeStateId, and HomeStateName (which will be retrieved from the reference table). OR should the interface not expose the structure of the database, i.e. NOT have HomeStateId, and just have Name, HomeStateName?
I'd say you're on the right track when thinking about property names!
Model your classes as you would in the real world.
Forget the database patterns and naming conventions of StateID and foreign keys in general. A person has a city, not a cityID.
It'll be up to your data layer to map and populate the properties of those objects at run time. You should have the freedom to express your intent and the representation of 'real world' objects in your code, and not be stuck to your DB implementation.
Either way is acceptable, but they both have their pros and cons.
The first way (entities have IDs) is analagous to the ActiveRecord pattern, where your entities are thin wrappers over the database structure. This is often a flexible and fast way of structuring your data layer, because your entities have freedom to work directly with the database to accomplish domain operations. The drawback is that when the data model changes, your app is likely to need maintenance.
The second way (entities reflect more of a real-world structure) is more analagous to a heavier ORM like Entity Framework or Hibernate. In this type of data access layer, your entity management framework would take care of automatically mapping the entities back and forth into the database. This more cleanly separates the application from the data, but can be a lot more plumbing to deal with.
This is a big choice, and shouldn't be taken lightly. It really depends on your project requirements and size, who will be consuming it.
It may help to separate the design a little bit.
For each entity, use two classes:
One that deals with database operations on the entity (where you would put IDs)
One that is a simple data object (where you would have standard fields that actually mean something)
As #womp mentioned, if your entity persistence is only going to be to databases, strongly consider the use of an ORM so you don't end up rolling your own.

Categories

Resources