I am a new bie to DDD. In our DDD project ,we have a requirement that our DBContext should only expose AggregateRoots.. Assuming that our DbContext is as shown below
public class ClassContext : DbContext
{
public DbSet<Class> Classes{ get; set; }
public DbSet<Students> Students{ get; set; }
}
and Class is the aggregate root . Is the following implementation the right way
public class ClassContext : DbContext
{
public DbSet<Class> Classes{ get; set; }
private DbSet<Students> Students{ get; set; }
}
Any comment is appreciated
It's certainly useful to think about aggregate roots in your application, but don't try to apply DDD concepts to an Entity Framework class model.
An Entity Framework class model is not a domain model. It's a data access layer. Any considerations regarding including or hiding entities and/or navigation properties should be motivated by facilitating smooth data access and nothing more.
It's highly unlikely that you're always going to read/create/update/delete students through classes only. That would make unnecessary clunky code. And who says that students will always be in a class?
But maybe this isn't the best example of an aggregate. A Student doesn't have an identifying relationship with a Class, because next time he'll be in another class. It would be different with the classic Order-OrderLine relationship. I can imagine that in that case you might only expose a DbSet<Order>.
So just expose the DbSet<Students> as public class.
I don't think the private declaration for Students is needed.
Presumably the Class object contains something like
public virtual List<Student> Students { get; set; }
so, given the requirement that you are only exposing aggregate roots,your code to find a student will always need to find a class and pull the student from it.
Related
I have two Model classes to be created using Entity Framework: Skill and Activity. The following are the definitions of each:
Skill.cs
public class Skill
{
public int Id { get; set; }
public String Name { get; set; }
}
Activity.cs
public class Activity
{
public int Id { get; set; }
public String Name { get; set; }
public virtual List<Skill> RequiredSkills { get; set; }
}
Ideally, in the database, I'd want the Activity to be linked via foreign key to a association entity (e.g. SkillActivityAssoc) and the Skill not to have to do anything with it. I don't need to track which activities need a certain skill. I just need to track what skills are needed for each activity thus explaining why I don't have a List in the Skill class. I hope that made sense.
My question is: Is this the right way to go about doing this? When I update the RequiredSkills property of Activity via:
activity.RequiredSkills = someInstanceOfRequiredSkillsList;
dbcontext.Entry(activity).State = EntityState.modified;
dbcontext.SaveChanges();
.., it doesn't work. I'm already speculating that it's because I'm not able to update the association entity. Moreover, my current implementation has a virtual List<Activity> property in the Skill class which I want to get rid of. How do I go about changing my model design and how do I update RequiredSkills accordingly?
Thank you in advance!
virtual is for lazy loading and track changes in EF. You can read more about it here: Understanding code first virtual properties. You should also read MSDN documentation about loading entities in EF: https://msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx
Since you want to have more than one Skills in each Activity and each Skills can be in more than one Activity as well, you have a many-to-many relantionship. Please read this example: How to create a many-to-many mapping in Entity Framework? and this http://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx
In my EF 6 Model First application, I have an entity with a many-to-many navigation property to another entity. In the first entity, I need to add several references to the same record in navigation property.
The first entity is a “saleslistItem” and the second entity is “warehouseItem”. Normally there will be a one-to-one relationship here, but exceptionally there will be some bundles where one “saleslistItem” contains several “warehouseItems”. “WarehouseItem” can also be included in several “salesListItems”. At the end of the project, my customer says, testing it, that “saleslistItem” must be able to consist of several “WarehouseItems” of the same kind (like two boxes of smoked ham).
These data is used several places in my code. (ie. doing a sale removes items from the warehouse) If I could just add several the same reference, my code would work without any modifications. But in the implementation of the navigation property the “hashtable”-collection is used, and this collection requires unique entries. Is there a workaround here? Performance is irrelevant as the data amount is small.
If there are no such workaround, is it possible to store values together with the instance of navigation property? Maybe it is implemented as a field in the join-table???
Any other suggestions?
Need a solution so the customer pays the last part of the bill!
So you currently have a 1:1 from SalesListItem toWarehouseItemvia a ForeignKey inSalesListItem`? Sounds like you need:
public class SalesListItem
{
public virutal ICollection<SalesListWarehouseItem> WareHouseItems { get; set; }
}
public class SalesListWarehouseItem
{
public virtual SalesListItem Parent{ get; set; }
public virtual WarehouseItem WarehouseItem { get; set; }
public int Quantity { get; set; } // maybe double?
}
On my own projects I use RavenDB. At work I use SQL Server and Entity Framework (code first).
So designing domain entities is a challenge, as I really enjoy RavenDB's ability to create an application-centric, DDD style application, that isn't tied at all to a database implementation.
At the moment I'm trying to persist an entity that has a collection of GUIDs that reference other entities in the system. For example (not the actual class, but the same concept):
public class Thing
{
public Thing()
{
this.VisibleSectionIds = new Collection<Guid>();
}
public Guid Id { get; set; }
public string Name { get; set; }
public ICollection<Guid> VisibleSectionIds { get; set; }
}
Using RavenDB, I can persist this in a few lines of code with no need to redesign the database. I can even make my collection of ids read-only.
Can people suggest ways that I could do a similar thing in EF without introducing mapping properties to other entities (this would break my DDD approach and possibly introduce N+1 issues). Can I use EF to convert my collection of GUIDs to a text datatype in the database and convert it back again?
Many to many relationships can be declared like this in fluent-API.
modelBuilder.Entity<Course>()
.HasMany(t => t.Instructors)
.WithMany()
I would rather if there were certain attributes that could do the same in my domain model.
Are there such attributes somewhere in the framework, or can I make some of my own that can affect EF behavior when it generates the database?
I've assumed your model, try below and see if it works.
public class Course
{
[InverseProperty("Courses")] //add this attribute
public ICollection<Instructor> Instructors { get; set; }
//other properties..
}
public class Instructor
{
[InverseProperty("Instructors")] //add this attribute
public ICollection<Course> Courses { get; set; }
//other properties..
}
that way you tell entity framework to look for what property to map with in the Course model for Instructor.
Moreover, you don't even need to define that way. but In case you have more than one property of type Course in Instructor or vice-versa, you will need to point out correctly which is mapped to what.
Still, using fluent API is much better and scalable and manageable
You don't need any attributes for it. If you declare ICollection<T> in each entity, EF will create many to many relationships by convention. See here.
I have an issue with poco classes in EF 4.
I have an Order entity wich contains a foreign key to a Customer entity.
So, the Order class has a navigation property of type Customer.
It's look like this :
public class Order
{
public virtual int Id { get; set; }
public virtual CustomerId { get; set; }
public virtual Customer customer { get; set;}
…
}
When I load an order, the navigation property customer is correct, but if the CustomerId property changes, the navigation property is not refresh with the new customer.
If I call the DetectChanges() method on the EF context, the navigation property is then refreshed.
I've read that with all properties marked as virtual, the relationship synchronisation is automatic, but it's not the case here.
Where did I go wrong ?
Thanks for any help
It means that for some reason proxy was not created for you entity. Take a look at this blog post - http://blogs.msdn.com/b/adonet/archive/2009/12/22/poco-proxies-part-1.aspx. Here are the requirements for creating proxies: http://msdn.microsoft.com/en-us/library/vstudio/dd468057(v=vs.100).aspx. Proxy creation must not be disabled.