DDD adding to a collection - collections

Consider the following scenario
I have an aggregate root of Fleet (as in a fleet of airplanes)
public class Fleet
{
public string Name { get; set; }
public Guid Id { get; set; }
public IEnumerable<Aircraft> Aircraft { get; }
public void AddAircraft(Aircraft aircraft)
{
}
}
public class Aircraft
{
public string Name { get; set; }
public Guid Id { get; set; }
public string IcaoCode { get; set; }
...
}
There are many fleets, and an aircraft can only belong to one fleet
When adding an aircraft to a fleet I need to check if it already belongs to a fleet and if it does, then stop the add from completing
What is the best way to do this? Is it a candidate for a service? If so, what would you do with the Add method on the Fleet object, it doesn't feel that this should be there any more, but how do I then actually add to the Aircraft collection

Related

EF Core one-to-many relationship with multiple contexts (databases)

I have contexts with entities like this:
public class CompanyContext : DbContext
{
public DbSet<StoreModel> Stores { get; set; }
// Other entities
}
public class DepartmentContext : DbContext
{
public DbSet<OrderModel> Orders { get; set; }
// Other entities
}
public class StoreModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<OrderModel> ReceivedOrders { get; set; }
public virtual ICollection<OrderModel> PreparedOrders { get; set; }
public virtual ICollection<OrderModel> IssuedOrders { get; set; }
}
public class OrderModel
{
public Guid Id { get; set; }
public string Details { get; set; }
public StoreModel GettingStore { get; set; }
public StoreModel PreparingStore { get; set; }
public StoreModel IssuanceStore { get; set; }
}
For example a user makes an order in storeA, but wants to receive it in storeC, and it order will preparing in storeB. And I needs a statiscics about store received/prepared/issued orders.
When I try to create a migrations, EF throws exceptions "Unable to determine the relationship represented by navigation 'OrderModel.GettingStore' of type 'StoreModel'" and "Unable to determine the relationship represented by navigation 'StoreModel.IssuedOrders' of type 'ICollection<OrderModel>'". If I understand correctly, this happens because entities are defined in different contexts.
Now I just use next model:
public class OrderModel
{
public Guid Id { get; set; }
public string Details { get; set; }
public Guid GettingStoreId { get; set; }
public Guid PreparingStoreId { get; set; }
public Guid IssuanceStoreId { get; set; }
}
This works fine, but perhaps there are options that allow to create such a structure using navigation properties, with correct relationships between these entities from different contexts(databases).
First, the map of a different database was not placed in tables of different application formats, so think that you have a domain that should be well defined in your application, that way you would have the mapping of your application like this:
public class DomainNameContext: DbContext
{
public DomainNameContext(): base()
{
}
public DbSet<StoreModel> Stores { get; set; }
public DbSet<OrderModel> Orders { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// config mapping methods
}
}
another thing, the relation you are using doesn't work so you can't have a repetition of Orders within the same class because this is not one -> many, this statement means that a StoreModel line can have many lines in the OrderModel this way would be like this
public class OrderModel
{
public Guid Id { get; set; }
public string Details { get; set; }
public Guid StoreModeId { get; set; } // this part will show the entity framework that this is the fk it will correlate
public StoreModel StoreModel { get; set; }
}
public class StoreModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<OrderModel> OrderModels { get; set; }
}
see that if you are wanting to have many StoreModel related to many OrderModel then you need to use many -> many which microsoft documentation foresees to use as well
good to map this within its context it is necessary in OnModelCreating to use its mapping like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// config mapping methods
modelBuilder.Entity<StoreModel>()
.HasMany<OrderModel>(g => g.OrderModels )
.HasForeignkey<Guid>(s => s.StoreModeId )
}
you can have a look at the microsoft documentation enter link description here, enter link description here
now if you need to map between contexts you will have to use dapper to make separate queries in separate bases the entity has support for that in this link enter link description here
and then you can make the necessary inner joins so that you can use it but natively this does not exist, I advise you to rethink your database so that it can make more sense to a relational model, perhaps putting types for your StoreModel and OrderModel so you can use the way I wanted the types GettingStore, PreparingStore, IssuanceStore using an enum for this to make it explicit

Entity Framework Core Navigation Properties and Joins, Correct Pattern

I'm struggling to understand the best way to implement some database relationships in EF Core.
Specifically, it involves the navigation properties, where you make a collection in the parent and an object in the child.
Looking at the MS docs here
Relationships, navigation properties, and foreign keys
there is the typical use case presented of a parent child relationship
public class Course
{
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
public int DepartmentID { get; set; }
public virtual Department Department { get; set; }
}
public class Department
{
public Department()
{
this.Courses = new HashSet<Course>();
}
public int DepartmentID { get; set; }
public string Name { get; set; }
public decimal Budget { get; set; }
public DateTime StartDate { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
Now this is fine for the above use case.
However, I am working on a specification system for process recipes. There are lots of machines, materials, areas, buildings and other things involved.
One of the tables in the database is "Unit", as in unit of measurement - that is kg, m, cm, etc.
This table is used as a lookup in many tables in the database, at least 20.
As such, if I've understood the recommended approach, I would end up with
pubic class Unit
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Recipes> Recipes{ get; set; }
public virtual ICollection<Coll2> Coll2{ get; set; }
public virtual ICollection<Coll3> Coll2{ get; set; }
public virtual ICollection<Coll4> Coll2{ get; set; }
public virtual ICollection<Coll5> Coll2{ get; set; }
public virtual ICollection<Coll..n> Coll..n{ get; set; }
}
This applies not just for unit, but also for quite a few other generic lookup items, such as a warehouse. There are many entities that use a link to the warehouse.
What is the correct approach when using this kind of lookup?
I'm sorry if things aren't clear, hopefully they are.

EF 5.0 Code First mapping issues between 3 entities

I've got 2 entities:
public class School
{
public int Id { get; set; }
...
public virtual ICollection<Seminar> Seminars { get; set; }
}
public class Seminar
{
public int Id { get; set; }
...
public virtual ICollection<School> Schools { get; set; }
public virtual ICollection<Price> Prices { get; set; } // wrong??
}
public class Price
{
public int Id { get; set; }
public decimal Value { get; set; }
public virtual School School { get; set; }
public virtual Seminar Seminar { get; set; }
}
How to map "Price" property for getting something like this:
var priceOfSomeSeminar = someSchool.Seminars[0].Price
Is it possible? So I think I need help with the Fluent API modelBuilder relationship establishment...
Well, ICollection doesn't have an indexer, so you can't use array syntax with it. You can, however, convert it to an IEnumerable and then convert that to a List, which can then be indexed.
But no, you are using the correct semantics, so this should just work. No need to work with the fluent api.
I think you have an error though, Price should not have a School member. There is no direct relationship between price and school.

MVC EF Code First one to one relationship error

I want to have a list of stands (at a trade show) and a list of exhibitors.
The list of stands is separate to the list of exhibitors - however, once registered, I want the exhibitor to be able to book a stand.
When they select/book a stand - I would like to then be able to have a list the stands in my view, and also show the associated exhibitor who has booked it.
Likewise, I would like to list in another view, the exhibitors, and also which stand they have booked.
So I'm trying to setup a one to one relationship (using EF CodeFirst).
However, when trying to add a controller for either the Stand or the Exhibitor, I get the following error:
My models are:
public class Stand
{
public int StandID { get; set; }
public string Description { get; set; }
public bool Booked { get; set; }
public int ExhibitorID { get; set; }
public virtual Exhibitor Exhibitor { get; set; }
}
public class Exhibitor
{
public int ExhibitorID { get; set; }
public string Company { get; set; }
public int StandID { get; set; }
public virtual Stand Stand { get; set; }
}
I'm certain it's something to do with the "Virtual" part of the models.
Can anyone please help point out what should be updated, to allow the connection?
Thank you,
Mark
EF doesn't know which entity is the principal (parent) and which is the dependent (child). You need to declare a foreign key on the item that entity that should come first. You can do this with an annotation or a fluent mapping.
Annotation
Add the following namespace:
using System.ComponentModel.DataAnnotations.Schema;
Annotate your Stand class with the following annotation:
public class Stand
{
[ForeignKey("Exhibitor")]
public int StandID { get; set; }
public string Description { get; set; }
public bool Booked { get; set; }
public int ExhibitorID { get; set; }
public virtual Exhibitor Exhibitor { get; set; }
}
Fluent Mapping
Override your OnModelCreating method in your DbContext class to include:
modelBuilder.Entity<Stand>()
.HasOptional(s => s.Exhibitor)
.WithRequired(e => e.Stand);
The model you have created is not possible to work with relational databases. The Stand needs an ExibitorId while Exibitor need a StandId. The cyclic relationship does not allow you to insert any rows to either tables.
Assuming an Exibitor may have more than one Stand and converting the relationship to one-to-many is one option.
public class Stand
{
public int StandID { get; set; }
public string Description { get; set; }
public bool Booked { get; set; }
public int? ExhibitorID { get; set; }
public virtual Exhibitor Exhibitor { get; set; }
}
public class Exhibitor
{
public int ExhibitorID { get; set; }
public string Company { get; set; }
public virtual ICollection<Stand> Stands { get; set; }
}
Or you can use shared primary key mapping to make the relationship one-to-one. Where Stand is the principal entity. The Exibitor will use the StandID as its PK.
public class Stand
{
public int StandID { get; set; }
public string Description { get; set; }
public bool Booked { get; set; }
public virtual Exhibitor Exhibitor { get; set; }
}
public class Exhibitor
{
public int ExhibitorID { get; set; }
public string Company { get; set; }
public virtual Stand Stand { get; set; }
}
Using the Fluent API to configure the relationship.
modelBuilder.Entity<Exibitor>().HasRequired(e => e.Stand)
.WithOptional(s => s.Exibitor);

What is the most efficient way to submit and save a form with several ICollection items?

I am having users fill out a form that requires a number of 'educational background' pieces of data:
public class EducationalBackground
{
public int EducationalBackgroundID { get; set; }
public string UniversityOrCollege { get; set; }
public string AreaOfStudy { get; set; }
public string Degree { get; set; }
public int YearReceived { get; set; }
public virtual Application Application { get; set; }
}
Here is the model for the full Application:
public class Application
{
public int ApplicationID { get; set; }
public Profile BasicInfoGatheredFromProfile { get; set; }
public virtual ICollection<EducationalBackground> EducationalBackground { get; set; }
public bool WillingToTravel { get; set; }
}
I am working on making a page where users can fill out the full application and it will render a partial view that allows them to add an "educational background" piece of data up to however many they have.
What would be the most efficient way to allow users to add in indefinite number of "education background" pieces of information in this application?
What I am thinking: I will need a ViewModel to allow for the IColleciton of EducationalBackground when I POST the form. Is jQuery the cleanest way to add additional fields for 'educational background'?
An example POST action would be appreciated in addition to any information one is able to provide.

Resources