With DDD there is a distinction between an Entity and an Aggregate. In EFCore I’m happy with the approach of using private collections and using a specification pattern to populate child entities when required. Similarly Julie Lerman and others have written really good articles on adapting EF for DDD.
An Aggregate, as opposed to an Entity, can/should only hold an Id reference to another Aggregate, rather than navigation property, which we can use to pull back via it’s Repository with a GetById() call.
What is more of a problem is determine how an Aggregate could hold a collection of Id references to a collection of Aggregates and how this can be achieved with Entity Framework?
Typically you’d set it up with navigation properties and foreign keys.
public Class Foo
(
public List<Bar> Bars { get; set; }
)
However, what I’m looking for to be in keeping with DDD is.
public Class Foo
(
public List<int> BarIds { get; set; }
)
What I don’t want to have is the Bar aggregate knowing that it has a relationship to Foo as it could be referenced by many other Aggregates.
Is it perhaps the case that you can’t have a collection of Aggregate Ids on an Aggregate?
How to correctly reference a collection of Aggregates?
You reference an aggregate by its id. So you reference a collection of aggregates by a collection of ids (each id references an aggregate).
how an Aggregate can hold an Id reference to another Aggregate
It's simple: the id of the another aggregate is a field in the aggregate that holds the reference.
how this can be achieved with Entity Framework?
I don't know EF, but an aggregate holds an id reference the same way it holds any other field of the aggregate.
I don't know the reason of the struggle.
Say you have 2 aggregates: Foo and Bar, so that Foo references Bar (Foo ==> Bar). If the client of Foo wants to get the instance of Bar referenced by an instance of Foo:
String aFooId = ...
Foo aFoo = fooRepository.getById ( aFooId );
String aBarId = aFoo.barId();
Bar aBar = barRepository.getById ( aBarId );
Related
I have a table for a spot. This spot can have different categories. For example: restaurant, hotel, park.
Each individual category has additional and different details.
My questions now:
Is it possible to create a column (FK) in the spot table that is independent of the category?
I mean when I create a new spot with the category Resteraunt and the next one is with the category park.
If I now select a spot that I get the correct data from the respective spot category
And if possible, how can I write that in C# EF Core Models?
Or is this not possible and i have to take another way?
Thanks in advance
Database Design for Example:
No, you can't have an FK column that is independent of the table it's referencing (the manifestations of your category). What you're looking for is inheritance. EF Core 5 currently supports two types of inheritance - Table Per Hierarcy (TPH) and Table Per Type. Either can work for your purposes.
First, you implement your entity Classe in an inheritance hierarchy to be mapped to the database with the derived classes representing the "category" of Spot:
public abstract class Spot
{
public Guid Id { get; set; }
// common spot properties here
// (i.e. props shared by different types of spots like address)
}
public class Restaurant : Spot
{
// restaurant specific properties here
}
public class Park : Spot
{
// park specific properties here
}
Then you map the entities in one of two ways - either to a single table (TPH) which will use a discriminator column to type each record in the DB (would be considered your category) and each property for the derived types would also be included but only populated for the specific type of record (i.e. Park properties will be null when the record in the DB represents a Restaurant and vice versa). Faster query performance with this method but all type-specific columns must be nullable and this implementation violates 3NF.
TPH is the default inheritance implementation but you can configure how it handles the discriminator like any other property (name, datatype) and specify the values to use for each derived type:
modelBuilder.Entity<Spot>()
.HasDescriminator("Category") // name it what you want
.HasValue<Restaurant>("R") // value for restaurants
.HasValue<Park>("P") // value for parks
;
In TPT each type in the inheritance hierarchy is mapped to its own table which contains their specific properties. The tables for the derived types use shared primary keys to reference their corresponding Spot record. Query performance can be slower and while it doesn't violate 3NF, its possible for manual data manipulation operations to mess things up (e.g. a Park and a Restaurant can reference the same Spot record).
For this configuration, merely map each type in the entity hierarchy to its own table:
modelBulider.Entity<Restaurant>().ToTable("Restaurant");
modelBuilder.Entity<Park>().ToTable("Park");
For both implementations, you can implement the DbSet properties normally:
public DbSet<Spot> Spots { get; set; }
public DbSet<Restaurant> Restaurants { get; set; }
public DbSet<Park> Parks { get; set; }
You can get specific types of Spots from Spots by using .OfType<T>()
var parks = dbContext.Spots.OfType<Park>();
So you do not need the Restaurants or Parks DbSet<T>s if you include the Spots DbSet<T>. Alternatively, Spots is optional if you include DbSet<T>s for the derived types.
I encourage you to model your entities both ways to see how EF models the DB and choose which you prefer.
https://learn.microsoft.com/en-us/ef/core/modeling/inheritance
I'm learning Entity Framework Core. I came across the term "Owned Entity" in almost all tutorials.
Here is one example on using an Owned Entity in Entity Framework Core
Job Entity:
public class Job : Entity
{
public HiringManagerName HiringManagerName { get; private set; }
}
HiringManagerName Value Object:
public class HiringManagerName : ValueObject
{
public string First { get; }
public string Last { get; }
protected HiringManagerName()
{
}
private HiringManagerName(string first, string last)
: this()
{
First = first;
Last = last;
}
public static Result<HiringManagerName> Create(string firstName, string lastName)
{
if (string.IsNullOrWhiteSpace(firstName))
return Result.Failure<HiringManagerName>("First name should not be empty");
if (string.IsNullOrWhiteSpace(lastName))
return Result.Failure<HiringManagerName>("Last name should not be empty");
firstName = firstName.Trim();
lastName = lastName.Trim();
if (firstName.Length > 200)
return Result.Failure<HiringManagerName>("First name is too long");
if (lastName.Length > 200)
return Result.Failure<HiringManagerName>("Last name is too long");
return Result.Success(new HiringManagerName(firstName, lastName));
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return First;
yield return Last;
}
}
Entity Configuration:
public class JobConfiguration : IEntityTypeConfiguration<Job>
{
public void Configure(EntityTypeBuilder<Job> builder)
{
builder.OwnsOne(p => p.HiringManagerName, p =>
{
p.Property(pp => pp.First)
.IsRequired()
.HasColumnName("HiringManagerFirstName")
.HasMaxLength(200);
p.Property(pp => pp.Last)
.IsRequired()
.HasColumnName("HiringManagerLastName")
.HasMaxLength(200);
});
}
}
And this gets created as two columns in table like other columns in Job Entity.
Since this is also created as columns just like other properties in entity this can directly be added as normal properties in the Job Entity. Why this needs to be added as Owned Entity?
Please can anyone help me understand,
What is owned entity?
Why we need to use owned entity?
When to use owned entity?
What does this look like without owned entities?
If you create an entity, Job, in EF Core that points to a complex object, HiringManagerName, in one of the properties, EF Core will expect that each will reside in a separate table and will expect you to define some sort of relationship between them (e.g. one-to-one, one-to-many, etc.).
When retrieving Job, if you want to explicitly load the values of HiringManagerName as well, you'd have to use an explicit Include statement in the query or it will not be populated.
var a = dbContext.Jobs
.Include(b => b.HiringManagerName) //Necessary to populate
.ToListAsync();
But because each is thought to be a separate entity, they will be required to expose keys and you'll have to configure foreign keys between each.
What is an owned entity?
That's where [Owned] types come in (see docs). By marking the child class with the [Owned] attribute, you leave the explicit handling of that relationship to EF Core to manage and no longer have a need to define the key(s)/foreign key(s) on the owned type. Same if you point to a collection of your owned type - you no longer need to deal with navigation properties on either class to describe the relationship.
EF Core also supports queries against these owned types, as in:
var job = context.Jobs.Where(a => a.HiringManagerName.First == "fingers10").FirstOrDefaultAsync();
Now, it comes with two important design restrictions described in the docs (but elaborated on here):
You cannot create a DbSet for the owned type
This means that you cannot subsequently do a DB call with:
dbContext.HiringManagerNames.ToListAsync();
This will throw because you are expected to simply retrieve the value as part of a call to:
dbContext.Jobs.ToListAsync();
Unlike the first example I gave, HiringManagerNames no longer needs to be explicitly included and will instead be returned with a call to the Jobs DbSet<T>.
Cannot call Entity<T> with an owned type on ModelBuilder
Similarly, you cannot reference your owned type in the ModelBuilder to configure it. Rather, if you must configure it, do so through the configuration against your Jobs entity and against the owned property, e.g.:
modelBuilder.Entity<Job>().OwnsOne(a => a.HiringManagerNames).//Remaining configuration
So when should I use owned entities?
If you've got a type that's only ever going to appear as a navigation property of another type (e.g. you're never querying against it itself as the root entity of the query), use owned types in order to save yourself some relationship boilerplate.
If you ever anticipate querying the child entity independent of the parent, don't make it owned - it will need to be defined with its own DbSet<T> in order to be called from the context.
While #Whit Waldo explanation is great with respect to technical ef core, we should also try to understand from Domain Driven Design perspective.
Lets observe the classes mentioned in the question itself
public class Job : Entity
and
public class HiringManagerName : ValueObject
Take a note at Entity and ValueObject. Both of them are DDD concepts.
Identity matters for entities, but does not matter for value objects.
Take a look at this write up from Vladimir Khorikov for a more extensive explanation.
I past the summary bullets here.
Entities have their own intrinsic identity, value objects don’t.
The notion of identity equality refers to entities; the notion of structural equality refers to value objects; the notion of reference equality refers to both.
Entities have a history; value objects have a zero lifespan.
A value object should always belong to one or several entities, it can’t live by its own.
Value objects should be immutable; entities are almost always mutable.
To recognize a value object in your domain model, mentally replace it with an integer.
Value objects shouldn’t have their own tables in the database.
Always prefer value objects over entities in your domain model.
So a value object is owned by an entity. So how do we achieve that using EF Core? Here comes the concept of Owned entities. Now go back and read #Whit Waldo answer.
I'm using Entity Framework - Database First in my project. My model has a view with only one VARCHAR column:
CREATE VIEW MyView
AS
SELECT 'Eris' Eris
FROM MyTable
By default, this view gets mapped to its own entity with just one property:
public virtual DbSet<MyView> MyViews { get; set; }
How can I change this so that the view gets mapped to a List of strings instead:
public virtual List<string> Eris { get; set; }
Unfortunately EF does not support mapping collections of value types. If you really want to implement this scenario then you might want to look into other ORM frameworks that have this feature like NHibernate.
If that's not an option and you have to stick to EF then you're forced to create an entity with one property like you mentioned in your question.
The entity model represents one element in the table.
When you retrieve data from the table, you will get a list of entity model objects.
trying to work out how to do LINQ to Entities query for a many to many relationship which has a junction with fields table.
Below are the Domains models (I am using View models, but keeping it simple for this example).
Student Domain model
StudentID (PK)
ICollection<StudentCourse> StudentCourses
StudentCourse Domain model
StudentCourseID (PK)
StudentID (FK)
CourseID (FK)
ForAdult
ForSeniour
Description
Course Domain model
CourseID (PK)
ICollection<StudentCourse> StudentCourses
Note:
Since the junction table (i.e. StudentCourse) contains fields other than the two foreign keys, EF will create an entity for this.
Lazy Loading
I've got this working for lazy loading. The Navigation properties have been declared with the 'virtual' keyword.
The Query way - works!
var student = (from s in context.Students
where s.StudentID == id
select s).SingleOrDefault<Student>()
The Method way - works!
Student student = context.Students.Find(id);
Projection
BUT, I would prefer to do this with projection, for performance reasons, i.e. less trips to the database.
I'm really stuck on how to write up the LINQ to Entities query to return 1 student with (1 or) many StudentCourses.
I don't understand thoroughly how the Entity should be shaped, if you know what I mean.
For example, I've tried:
var myvar = from s in context.Students
from sc in s.StudentCourses
where s.StudentID == id
select s
What I require is to return an entity of Student with a collection of StudentCourses which could then be assigned to a Student and passed to the View model, then to the View.
Really would appreciate any help, as I've spent alot of time trying to solve this.
Also as a side note, I'm using the SingleOrDefault() method to cast the results of the var (IQueryable I think) to type Student. Is this the preferred way to cast?
You can get EF to eagerly load the related entities by using the Include method.
So using your LINQ example:
var student = (from s in context.Students
where s.StudentID == id
select s).Include("StudentCourses").FirstOrDefault();
And using extension methods:
var student = context.Students.Include("StudentCourses").FirstOrDefault(id);
The Student instance that is returned will have the StudentCourses collection populated with related entities. This should invoke only one SQL query that joins the tables together.
To answer your aside question: I prefer to use FirstOrDefault most of the time as above. The difference is that SingleOrDefault will expect exactly one result and throws an exception otherwise, whereas FirstOrDefault will return null if a student is not found.
Also, as the cast to Student is implicit, you don't need the <Student> type parameter.
Starting out on an Entity Framework project.
Imported the Db I am going to use and right away noticed that many table fields were made into EntityKey types and the source fields are not even Keys. Doesn't seem to be a pattern as to which fields were made EntityKeys and which were not.
Is this normal? There were no options for this in the wizard. I don;t want to have to go through and remove this property for all the fields where it was added.
Thanks for your advice!
Each entity on your model requires a unique key, so EF can track and retrieve/persist these entities based on their unique identifier.
If your tables in your database don't have primary keys, then your database is not relational and therefore should not be used by an ORM like EF which is predominantly designed for RDBMS.
If you had an entity like this:
public class Orders
{
public string Name { get; set; }
public double Price { get; set; }
}
How would you retrieve a single order? How would you save a single order?
Crucial LINQ methods such as SingleOrDefault() would be useless, as there is no guarantee that this won't throw an exception:
var singleOrder = ctx.Orders.SingleOrDefault(x => x.Name == "Foo");
Whilst if you had an EntityKey and PK called "OrderId", this is guaranteed to not throw an exception:
var singleOrder = ctx.Orders.SingleOrDefault(x => x.OrderId == 1);
http://msdn.microsoft.com/en-us/library/dd283139.aspx
I think as soon as you read the first paragraph you will understand the role of entity keys in Entity Framework.