I am trying to explore if there are different ways than how I am used to using EntityFramework and relationships between data models.
Let's say, I have the following two classes:
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
}
public class Employee
{
public string JobDescripion { get; set; }
}
Let's assume there is a One to Many relationship between these two models in the database, with the many on the Employee class.
I would map this as follow:
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
//Navigational Property
public ICollection<Employee> Employees { get; set; }
}
public class Employee
{
public string JobDescripion { get; set; }
//navigational property
public virtual Person Person { get; set; }
}
This for me, takes away the principle of Object Orientated, as the Employee now do not Inherit from the Person class anymore, or at least, from my understanding.
Is this proper design, and would still be considered good Object Orientated Code, or is there a better way to be handling this, if for instance, I would like the following inheritance in my code:
public class Employee : Person
How would EntityFramework handle this?
Related
Have and "Address" model used by several other models ("Employee" & "Client").
I would call this a one to one relationship, I could be wrong. The address is required by both of the other models. Remove, deletes only the parent object.
Tried in both EF Core and EF6. Remove deletes the parent object, but not the "Address" object.
public class Address
{
public int AddressID { get; set; }
public string Street { get; set; }
public string CityStateZip { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
[Required]
public virtual Address EmployeeAddress { get; set; }
}
public class Client
{
public int Id { get; set; }
public string Name { get; set; }
[Required]
public virtual Address ClientAddress { get; set; }
}
No error messages - context.remove simply won't delete the child object. Complete noob here when it comes to EF. Sorry, this is probably a very basic question, but please believe that I have searched extensively. Most solutions suggest a foreign key back to the parent - but, in this case, the child object can be used (but not shared) in several different models.
The same Address object can be used in multiple Employee and/or Client instances as currently implemented.
The suggestion you received
Most solutions suggest a foreign key back to the parent - but, in this case, the child object can be used (but not shared) in several different models.
informs Entity Framework that a given Address can only appear in one specific Employee/Client.
You should be able to resolve this by having Employee and Client inherit from a common base class, e.g.
public class Person
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
[Required]
public virtual Address PersonAddress { get; set; }
}
public class Employee : Person
{
// Other properties that make Employee unique go here
}
public class Client : Person
{
// Other properties that make Client unique go here
}
Then add the backreference to the base class
public class Address
{
public virtual int AddressID { get; set; }
public virtual string Street { get; set; }
public virtual string CityStateZip { get; set; }
[Required]
public virtual Person AddressOf { get; set; }
}
I'm testing the following scenario (code below): create a shopping mall, with shops, with cashiers, with cash desks and persons operating it.
So I've created the following classes
Table Mall
Table Shop
Table CashDesk
Table Person
Basic classes with an ID and a name.
Then I need a derived class from Person being PersonCashier or PersonCustomer.
Since everything is related, I need to create intersection tables for the many to many scenarios.
I've created the following intersection tables:
The Mall contains shops: MallShop
The shop contains CashDesks: MallShopCashDesk
And the CashDesk containing cashiers: MallShopCashDeskPersonCashier
This just doesnt feel right. Can anyone help me out on a best practice
public class Mall
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
[Required]
public int NumberOfShopSpaces { get; set; }
}
public class Shop
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
}
public class CashDesk
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class Person
{
public int Id { get; set; }
[Required]
public string FullName { get; set; }
[Required]
public string Gender { get; set; }
}
public class PersonCashier : Person
{
[Required]
public int ShopId { get; set; }
public virtual Shop Shop { get; set; }
}
These are the base classes. How should i add a shop to a mall, a cashdesk to a shop, and a cashier to a cashdesk? (i've tried alot but posting the code would make the question look like spaghetti)
If this is code first then EF will make the relationship tables for you. You just need to add the relationships in your classes.
Exactly what they should be is not clear from your description because it depends on what relationships you want; if you want a many-many between PersonCashier and CashDesk it would be like this:
public class CashDesk
{
public List<PersonCashier> Cashiers { get; set; }
}
public class PersonCashier : Person
{
public List<CashDesk> CashDesks { get; set; }
}
(not showing all the fields for brevity)
public class Mall
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
[Required]
public int NumberOfShopSpaces { get; set; }
List<Shop> CurrentShops { get; set; }
}
public class Shop
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
public List<CashDesk> CashDesks { get;set; }
}
I added the list of shops to the Mall class and CashDesks to Shops. This gives you a list of shops in the mall, and a list of cashdesks in each shop and you can follow this method for everything else you need.
If you have a database, you will have a Mall table and a Shop table.
The Shop table can have a Foreign Key to the Mall table, that's how you link them and this will work with the class structure at the top.
Or, you can have another table called MallShops where you have 2 fields, one being the MallID, the other the ShopID. This is called a Link table.
Both approaches will work with the second allowing a more complex structure with lots of Malls linked to Lots of Shops.
I would start with the database structure first, make sure you cover all you need, then you can do the classes etc in a way that makes sense. If you use something like EntityFramework then it will create all the classes for you once your database structure is ready.
I am working on entity framework code first pattern. I have one scenario where i have following entities,
public class Toy
{
public int ID {get; set;}
public string Name {get; set;}
}
for the above entity, all model building configuration has been done and table was created fine.
We have another entity,
public class Kid
{
public string Name {get; set;}
}
For this entity also, all model building configuration has been done and table was craeted fine in database.
Now i need to maintain/configure, one -many relationship between kid and toys i.e. one kid can have multiple toys
so i have create one custom class which will inherit Kid class,
public class KidToy : Kid
{
public virtual List<Toy> Toys{get; set;}
}
Note: I can't add List Toys property directly in Kid class, i am
getting circular refernce error.
builder.Entity<Kid>().Map<KidToy>(m => {
});
builder.Entity<KidToy>().HasMany(b => b.Toys).WithMany().Map(b =>
{
b.MapLeftKey(KidId");
b.MapRightKey("ToyId");
b.ToTable("kidToyMap");
});
I dont need table creation for the custom model class (KidToy) and i need to configure one-many relationship. Could you please guide me.
use this :
public class Toy
{
public int ID { get; set; }
public string Name { get; set; }
public int KidID { get; set; }
[ForeignKey("KidID")]
[InverseProperty("Toys")]
public virtual Kid Kid { get; set; }
}
public class Kid
{
public string Name { get; set; }
[InverseProperty("Kid")]
public virtual ICollection<Toy> Toys { get; set; }
}
Model:
public class Student
{
public int StudentID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Gender Gender { get; set; }
public string Address { get; set; }
}
DBContext:
public class MyContext : DbContext
{
public MyContext():base(connectionstring)
{
}
public DbSet<Student> Student { get; set; }
}
Wrapper Class:
public class StudentWrapper
{
public int StudentID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Gender Gender { get; set; }
public string Address { get; set; }
}
Implementation:
public void AddStudent()
{
using(MyContext ctx = new MyContext())
{
StudentWrapper newStudent = new StudentWrapper(); // If ever I wanted this `working`
ctx.Student.Add(newStudent);
}
}
I want to make a wrapper for my model classes instead of directly using my models in CRUD operations, is this right to do so?
IMHO,
It is not a good idea untill you want to write some custom logic in the wrappers. I think you are using your model ( or rather i would say DTO objects) for communication purpose.
If you add wrapper than you need to also map it back to your DTOs. (AutoMapper can be helpful)
So , until you have very specific reason to do this than it does not make sense to create wrapper to me. One of the scenario would be writing an application in WPF or Silverlight where you want a change aware model (i.e. Model implementing INotifyPropertyChanged Interface)
Also , if you need to extend the behavior of your model , think about the extension methods before inheritance.
Given an Employee entity and bunch of personal/organization-related information (like marital status, children information, department, position). Is all personal information to be represented as components/value objects or it is better for the information to reside inside the entity class?
Would using a person (which could gather all personal info) value object as an underlying object (composition) for an Employee entity be a bad design choice?
Also how would such a behaviour modelled properly (in terms of DDD): If employee has kids then it should have a birth certificate (with corresponding data: name, issue date, etc) or If employee is married then it should have marriage certificate (with corresponding data: spouse name, etc)?
For a kids case I decided to use ChildrenInformation value object:
public class ChildrenInformation
{
public String BirthCertificateCode { get;set; }
public DateTime BirthCertificateIssueDate { get;set; }
public ChildName { get; set; }
public ChildMiddleName { get; set; }
public ChildLastName { get; set; }
public DateTime ChildBirthday{ get; set; }
}
public class Employee : AbstractEntity<Employee>, IAggregateRoot
{
public ISet<ChildrenInformation> ChildrenInformation { get; set; }
/* other things ...*/
}
Wouldn't it be wrong from a design view?
EDIT
Another thought is to share Certificate class.
[Serializable]
public class Certificate
{
public String Code { get; set; }
public String Number { get; set; }
public String RegistreeName { get; set; }
public Address RegistreeAddress { get; set; }
public String RegistreeDateOfBirth { get; set; }
public String RegistredAt { get; set; }
public DateTime DateRegistred { get; set; }
}
[Serializable]
public class Employee : AbstractEntity<Employee>, IAggregateRoot
{
public Certificate Passport { get; set; }
public Certificate MarriageCertificate { get; set; }
public ISet<Certificate> ChildrenBirthCertificates { get; set; }
}
Thanks!
I would model it like this:
public class Person
{
public String Name { get; set; }
public String MiddleName { get; set; }
public String LastName { get; set; }
public DateTime Birthday { get; set; }
public BirthCertificate BirthCertificate { get;set; }
public MarriageCertificate MarriageCertificate { get;set; }
// ...etc...
}
public class Certificate
{
public String Code { get;set; }
public DateTime IssueDate { get;set; }
// ...etc...
}
public class BirthCertificate: Certificate
{
public DateTime BirthDate { get;set; }
// ...etc...
}
public class MarriageCertificate: Certificate
{
public String SpouseName { get;set; } // or Spouse could also be a person
// ...etc...
}
public class Employee
{
public ISet<Person> Children { get; }
// ...etc...
}
Some points:
Note the ? usage which means certificates are optional.
Certificate deserve their own types. If you have more than one property that start with the same prefix, most of the time, it means you can define an object off them. I have also created a base Certificate class because they may share some common properties and behavior.
Children is a collection of Person objects.
Spouse could also be a person, if you will (the property would then be named Spouse).
I don't repeat the declaring type name in a property name: Name instead of PersonName
Given an Employee entity and bunch of personal/organization-related information (like marital status, children information, department, position). Is all personal information to be represented as components/value objects or it is better for the information to reside inside the entity class?
I would put all of the given examples as properties in the employee entity. I don't see any benefit in having them as value objects?
Would using a person (which could gather all personal info) value object as an underlying object (composition) for an Employee entity be a bad design choice?
This is more of a domain question. I normally do not use inheritance but use Customer and Employee (instead of a Person entity) as to different models not related to each other.
Please note that the design concept of composition has nothing to do with the CLR concept of a value type. Composition just means that the life-time of the owned object is bound to the life-time of the owner. This can also be achieved with reference types, for example if the owner is the only one with a reference to the owned object.
That said, the solution from Simon is just fine.