C# Family Class Design - c#

I am working on building a single family unit (class) for an application. I've done some searching and found solutions for entire family trees, but this app doesn't care about anything outside the single family unit which is defined as (Father, Mother, Child1, Child+n)
This application is about the children (activities they can do based upon age and skill levels), but needs references to the parents. The parents are only needed for reporting purposes and are required to have driver's license and insurance on file.
The application is being built using C# & EF Code First. None of the database annotation elements have been added to the class yet as that isn't the problem.
Below are my classes. The main business rule state that each sibling will have his/her own record, but they need to be linked together so only one mailing (electronic or snail) is sent, if the parents live together. If the parents are divorced, then two letter (or emails) need to be sent.
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Suffix { get; set; }
public string Sex { get; set; }
public DateTime DOB { get; set; }
}
public class Youth : Person
{
public string CurrentGrade { get; set; }
public Adult Mother { get; set; }
public Adult Father { get; set; }
public Adult ICE { get; set; }
public virtual Adult Adult { get; set; }
}
public class Adult : Person
{
public string DriversLicense { get; set; }
public string StateIssued { get; set; }
public string AutoInsuranceCarrier { get; set; }
public string PolicyNumer { get; set; }
public string MaritalStatus { get; set; }
//foreign key
public int VehicleId { get; set; }
public virtual Vehicle Vehicle { get; set; }
}
public class Address
{
public int AddressId { get; set; }
public int PersonId { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public virtual Person Person { get; set; }
}
The logic pattern I was stuck in was that siblings will have the same AddressId. That failed when I applied the divorced parents, each having one child at their address. As far as mailings go, it would work because they are at different addresses. It doesn't feel like the best design. If this were handled by UI, then it would work.
My next thought was to create a Family class and add each family member to it. In this instance, the user would have to make the selection of which people would be living at which address.
public class Family
{
public int FamilyId { get; set; }
public int AddressId { get; set; }
public List<Person> Person;
}
That also doesn't seem like the best solution. I feel there is a better design. I just cannot find it on my own.
Are there any pitfalls to one of these approaches that I'm not seeing yet?
Can someone point me in a better direction? And explain why that direction is better?
Thanks in advance for all your insights!

The "Father", "Youth", "Brother", etc... is not attribute of the person, but attribute of relationship between persons. One person can be both "Father" and "Brother" and "Uncle".
Better design is something like this (i don't know all your requirements):
public class Person {
public Name{get;set;}
// etc...
public List<Relationship> Relationships{get;set;}
}
public class Relationship {
public Person P1{get;set;}
public Person P2{get;set;}
public RelationshipKind Kind{get;set;}
}
public class RelationshipKind {
// for example: Father
public Name1 {get;set;}
// for example: Child
public Name2 {get;set;}
}

Typically you want to keep your models flowing as you would think about them.
For instance, I would not have an Address class that contains Person. I would have an Address class containing only base data about the Address. In Person, I would have an Address. This fits with the "Person lives at this address" and will likely fix your who-lives-where issue. This is the type of setup you have for "Vehicle"

Without going into details regarding whole design, I will focus only on the address issue.
I recommend that you have your address class defined in a way that it does not have navigation property back to a person:
public class Address
{
public int AddressId { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
Then I would link your Adult (or even Person) class to Address like so:
public class Adult : Person
{
public string DriversLicense { get; set; }
public string StateIssued { get; set; }
public string AutoInsuranceCarrier { get; set; }
public string PolicyNumer { get; set; }
public string MaritalStatus { get; set; }
//foreign key
public int VehicleId { get; set; }
public virtual Vehicle Vehicle { get; set; }
public int AddressId {get; set;}
public virtual Address Address { get; set; }
}
With this approach, if parents are not divorced, they can share the same address instance. In case they are divorced, your application has to set different address for one of the parents. In case you need to find people living under same address, you can do sth like this:
_dbContext.Persons.Where(p => p.AddressId = addressId) ...

If you have a table of States then you can use that in a lot of places: DriversLicenseState, AddressState, InsuranceState etc. If this isn't a blank string then you don't have to validate the user input and can just put a drop-down on the application.
String current grade. If you instead enter the year the child entered first grade then you don't have to manually update this every year; it can be calculated - though you also have to include an int for NumberOfYearsHeldBack. But its less work to update that int once in a great while, than update every student every year.
Personal Preference: I like 'NameLast' and 'NameFirst' rather than 'FirstName' & 'LastName' just because it means these properties will bunch together alphabetically in all the IDE drop downs etc, just like AddressID, Address1 and Address2
You might consider making 'Mother' into a nullable 'Mother?' and the same with 'Father' to 'Father?'. Some kids simply don't have both parents. If you want to be politically correct you might consider 'Parent1?' and 'Parent2' and put an enum on the relationship to select mother, father, guardian because some kids have 2 moms or 2 dads or their older brother is their legal guardian.
In your address class why is there a person property when you already have a PersonID property? For that matter why does the address have a personID at all? This only needs to be one-way. A person has an address, but an address doesn't have a person. This way you can have 5 people all with the same address. If you try to keep both synchronized two-way it will get fouled up, not to mention you have to have a List<> of personID inside the address. Since address is a type, add another one to each person so you have an AddressPhysical and AddressMailing. Now you can have 4 kids each with different places they sleep but they all get their mail at grandma's P.O.Box.
I wouldn't add a third adult to the child as their ICE. Instead I would make a List<> of adults (its just going to be a list of ID ints really) That way you can keep working down the list in an emergency until you reach someone.

Related

How do I relate the data from my entities? ASP.NET MVC 5 EF 6

I'm building an ASP.NET MVC application and I'm not quite sure how to make some relations between my entities.
I have the following entities
namespace Entities
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
public class Classroom
{
public int Id { get; set; }
public string Name { get; set; }
public int Capacity { get; set; }
}
public class CoffeeSpace
{
public int Id { get; set; }
public string Name { get; set; }
public int Capacity { get; set; }
}
}
My problem is this: a training event is going to happen in a school. The people will be distributed in classrooms with variable capacity and the training will happen in two steps. There will also happen two coffee breaks with two distinct areas.
The application should allow to:
Register people with name and surname;
Register classrooms with name and capacity;
Register coffee areas with name and capacity.
The difference in the number of people in each classroom should be of at maximum 1 person. To stimulate the knowledge exchange, half the people in each classroom should move to another classroom between each step of the training.
When consulting a person registered in this event, the application should return the classroom this person will stay in each step of the training and the area where they will do each coffee break.
When consulting a classroom or coffee area registered in this event, the application should return a list of people that will be in that classroom/area in each step/break of the event.
I'm new to programming in general, and I know there are some kind of relations you can do between your entities using entity framework, but looking at it I'm completely lost and I can't seem to understand what type of relation I should use in this problem.
I would resolve this problem with middle tables 'between' Person and Classroom, would name it PersonxClass:
public class PersonxClass
{
public int Id { get; set; }
public int PersonId { get; set; }
public int ClassId { get; set; }
}
in this entity I will save persons that are in a specific Classroom. good, second step, I will do another entity 'between' Person and CoffeeSpace, would name it PersonxCoffee:
public class PersonxCoffee
{
public int Id { get; set; }
public int PersonId { get; set; }
public int CoffeeId { get; set; }
}
Equals that the before case, in this entity i will save data of persons for each CoffeeSpace.
I wait that this info is help for you.

Entity Framework Code First One to One Cascade Deletes

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; }
}

Entity Framework: how to solve table in table

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.

How to auto save complex model with lists of models in it?

I am creating a quiz creator module. There are 5 subjects. Each subject has 2000 questions.
Say, it's called "Create Full model test", and it will contain 100 questions, 20 questions from 5 subjects. So, 20*5=100
In the UI, creator will first select "Create full model test" from the drop down. Suppose if he select the "Full model test". He will have to select one subject among 5 subjects, then he will have to select 20 questions per subject. and then will have to save them into that "Full model test" segment.
If he selects English, he will have to select 20 questions, then he will have to select another subject, for example, physics, and will have to select another 20 questions for physics, then he will have to select maths and then will have to select another 20 questions and so on for maths. Finally 100 questions will be submitted by the form.
Now, my question is, how can I auto save the selected questions into that "Full model test" segment, so that he can continue saving 5 subject's questions before he submit the form.
Here is my Department model:
namespace MvcBCS.Models
{
public class Department
{
[Key]
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
public string DepartmentCode { get; set; }
public virtual ICollection<Subject> Subject { get; set; }
public virtual ICollection<Section> Section { get; set; }
public virtual ICollection<Subsection> Subsection { get; set; }
}
}
Here is my Subject Model:
namespace MvcBCS.Models
{
public class Subject
{
[Key]
public int SubjectId { get; set; }
public string SubjectName { get; set; }
public string SubjectCode { get; set; }
public int DepartmentId { get; set; }
public virtual Department Department { get; set; }
public virtual ICollection<Section> Section { get; set; }
}
}
Here is the Section Model:
namespace MvcBCS.Models
{
public class Section
{
[ForeignKey("Department")]
public int? DepartmentId { get; set; }
public virtual Department Department { get; set; }
[ForeignKey("Subject")]
public int? SubjectId { get; set; }
public virtual Subject Subject { get; set; }
[Key]
public int SectionId { get; set; }
public string SectionName { get; set; }
}
}
Here is the subjection model:
namespace MvcBCS.Models
{
public class Subsection
{
[ForeignKey("Department")]
public int? DepartmentId { get; set; }
public virtual Department Department { get; set; }
[ForeignKey("Subject")]
public int? SubjectId { get; set; }
public virtual Subject Subject { get; set; }
[ForeignKey("Section")]
public int? SectionId { get; set; }
public virtual Section Section { get; set; }
[Key]
public int SubsectionId { get; set; }
public string SubsectionName { get; set; }
public string SubsectionCode { get; set; }
}
}
All that you need is just to store all temporary data on client side.
And when you get complete pasts or even full set of data - send it to server using POST/JSON/XML/etc.
I think it such case it will be better for you to use some kind of JavaScript frameworks, for example KnockoutJS, which with only few click's and couple lines of code will allows you to store all your data on client side in object-based model.
Anyway if you will use any framework or not, you should use JavaScript to store all of your data, including question, answers and subjects. JavaScript will allows you to store,validate and send all data that you need.
To make your work with JavaScript easier and faster - you can use jQuery library which contains functions for interaction with both DOM structure and server side.
To make learning of KnockoutJS easier just use tutorial: http://learn.knockoutjs.com
This is how I am going to attempt it.
business rules:
- full model test will be completed if all the subjects questions are submitted by certain user.
Assumption: we knew in advance that we have five subjects. Therefore
public enum Subject
{
English,
Physics,
...
}
Test Poco entity structure:
public class Test
{
public int Id{get;set;}
public User CreatedBy{get;set;}
public Subject Subject{get;set;}
public bool IsFullTestCompleted{get;set;}
public string Question1{get;set;}
public string Question2{get;set;}
...
}
Assumptions:
You can use partial views/ajax/Jquery/Angularjs/Knockout whatever suits you best in your problem context to implement it to auto save the changes
You will add necessary view model with appropriate validation annotations/attributes
you will add validation where necessary.
you will add/update the Test entity. like for first subject you will add data into Test entity, and subsequently you will update it.
Hope it will be helpful

Data modeling for Country,Region,City

Im want to create a data structure for using within my MVC3 application. The site holds videos uploaded by users, I want to be able of setting up a location for the video so later on you can search based on the country, region or city.
The modeling of those entities is not a big problem to me, my question is which class attribute should I use for my video entity.
public class Country
{
int CountryId
string CountryName
}
public class Region
{
int RegionId
string RegionName
int FK_CountryId
}
public class City
{
int CityId
string CityName
int FK_CountryId
int FK_RegionId
}
........
public class Video
{
int VideoId;
string VideoName;
**Location VideoLocation;**
}
**public class Location
{
int LocationId;
Country CountrId;
Region RegionId;
City CityId;
}**
My initial idea, but I think it is not a really good design since you can have 2 identical rows for a Location, where it should be ideal to keep a unique reference to Locations
What do you think in terms of good design and performance?
That is everyone's nightmare I guess. Well...at least that was my nightmare when designing one of the applications.
Depending on your secenario you might keep countries, cities, regions as different entities. Everything is find with that approach until you want the user to select either country, region or city. Looks like you would need to have nullable fields, which is not really the best practice, because you would then have to fully rely on application logic to maintain data integrity.
Example of that approach would be:
public class Country
{
public string Code { get; set; } //country ID would not make sense in this approach
public string Name { get; set; }
}
public class Region
{
public string Code { get; set; }
public string Name { get; set; }
public string CountryCode { get; set; } //1 region is assigned to only 1 country
}
public class City
{
public string Code { get; set; }
public string Name { get; set; }
public string RegionCode { get; set; } //1 city is assigned to only 1 region
}
It looks good, simple to understand but think about the table where you capture what's been selected. If you only care about city (last item in dependency list), it's all clear and fine.
public class UserSelectionWithCityOnly
{
public string CityCode { get; set; }
}
Pretty easy and straight forward? Looks like it is.
Consider the scenario where you can select either country,city or region....it get's really messy:
public class UserSelectionWithEitherSelected
{
public string? CityCode { get; set; }
public string? RegionCode { get; set; }
public string? CountryCode { get; set; }
}
well...you could always check if CityCode.HasValue, but from DB point of view that would be a nullable field, which can add dirty data (should be fine if you are not pedantic about having neat and clean DB)
So they way I solve this was by creating one hierarchical table with parent item id :
public class MySolutionForDestinations
{
public int DestinationId { get; set; } //primary key
public int ParentDestinationId { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public DestinationLevel Level { get; set; }
}
public enum DestinationLevel
{
Country = 0,
Region = 1,
City = 2
}
it's probably not the most elegant solution, but it works really well. In this approach you only care about DestinationId which can be a country Id, region Id or a city Id, so you would definitely avoid having dirty data and can implement 1 to 1 mapping.
Hope this will be usefull

Categories