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
Related
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.
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.
Working in one project (Catering theme ) when I was designing the database I didn't take care about some thing , and now Is very hard to avoid some kine of errors(Circular error).
Suppose I have following scenario :
I have Meal object that should be composed from a list of semi-finished products (we will call it Product ) and list of simple Resources.
One Product is composed from a list of Resoruces and list of products.
So in real example this will look like this:
Meal: Pizza that contains list of Resoruces(cheese,dough) and list of Products : in our case will be just :Sauce.
Sauce will be composed from List of Resources(salt,Some cheese ,tomato Sauce) and a List of Products (in our case will be just one "Chopped tomatoes with salt")
So now I have following classes:
public class Resource
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ProductToProduct
{
public int Id { get; set; }
public Product MainProduct { get; set; }
public Product Component { get; set; }
public double Quantity { get; set; }
}
public class ProductToResource
{
public int Id { get; set; }
public Product Product { get; set; }
public Resource Resource { get; set; }
public double Quantityt { get; set; }
}
public class Meal
{
public int Id { get; set; }
public string Name { get; set; }
public IList<MealToProduct> MealToProducts { get; set; }
public IList<MealToResource> MealToResources { get; set; }
}
public class MealToResource
{
public int Id { get; set; }
public Meal Meal { get; set; }
public Resource Resource { get; set; }
public double Quantity { get; set; }
}
public class MealToProduct
{
public Meal Meal { get; set; }
public Product Product { get; set; }
public double Quantity { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public IList<ProductToResource> ProdcutToResources { get; set; }
public IList<ProductToResource> ProductToProducts { get; set; }
}
My problem is in relation between Product to Product.
Suppose I will have Product1, Product2 , Product3 , Product4.
Product 1 will be composed from something and Prodcut2, Product4.
Product2 will be composed from something and Prodcut3.
Prodcut 3 will be composed from something and Prodcut4.
Prodcut 4 will be composed from something and Prodcut1 , in this case when I will try to calcualte Cost for Product1 , or Product 4 I will get an Circular error.
So my problem is in ProductToProduct table.
My question is how I must to design tables to avoid this kind of errors .
I AM VERY SORRY FOR MY EXPLICATION BUT IT IS VERY HARD TO EXPLAIN THIS PROBLEM.
PLEASE ASK ME IF SOMETHING IS UNCLEAR.
THANKS FOR YOUR ATTENTION.
Note:This is not so important for this case but I am working in ASP.Net mvc , orm is Fluent Nhibernate.
Here's an example of a function you could use to detect whether a parent-child relationship exists. I have assumed that the product relationships are described in a table called ProductLink, which has two foreign keys to Product: ParentProductId and ChildProductId.
This function uses a recursive query to determine the complete list of products which are children of the product denoted by the argument #ParentProductId, then does a simple test to see whether #ChildProductId appears in that list.
create function dbo.ProductRelationshipExists
(
#ParentProductId int,
#ChildProductId int
)
returns bit
as
begin
declare #ChildExists bit = 0;
with ProductChildCTE as
(
-- Base case: Get the parent's direct children.
select ChildProductId from ProductLink where ParentProductId = #ParentProductId
-- Recursive case: Get the children's children.
union all
select
ProductLink.ChildProductId
from
ProductChildCTE
inner join ProductLink on ProductChildCTE.ChildProductId = ProductLink.ParentProductId
)
select #ChildExists = 1 from ProductChildCTE where ChildProductId = #ChildProductId;
return #ChildExists;
end
When someone tries to insert a record into ProductLink, you could use a test like this to determine whether the proposed parent and child are already in the table as child and parent, respectively, and disallow the insertion if so.
This was just a quick write-up to illustrate one possible approach; I should mention that I don't know how well the performance of this thing will scale as the table gets larger. Hopefully it will suffice for your case. If not, let me know how to improve 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
What is the proper way to show "Admin Tables" in my "Business Objects"? I have the following on my Address object.
public class Address
{
public int AddressID { get; set; }
public KeyValuePair<short, string> County { get; set; }
...
}
Now how would I instantiate this object, as far as the KeyValuePair<,> properties go?
My guess is:
var myAddress = new Address { AddressID = 3, County = new KeyValuePair<short, string>(32, "La Crosse")}
EDIT
This is what I am replacing with the KeyValuePair<> on the recommendations of another Programmer.
.....Address.cs.....
public County County { get; set; }
.....County.cs.....
public class County
{
public short? CountyID { get; set; }
public string CountyName { get; set; }
}
Is there a better way between the two or a third way that is even better?
KeyValuePair<T1, T2> buys you nothing in this case.
Why not just be explicit?
public class Address
{
public int AddressID { get; set; }
public int CountyCode { get; set; }
public string CountyName { get; set; }
}
or another version would be that you define a type County with the two properties, then have a property of that type instead.
In code, clarity is king.
I just ran your code, and it worked as expected.
The country property has correct value Key = 32 and Value = La Crosse.
Your new code is ugly. I'd either remove the setter of the Country property, or make the Country class immutable. This kind of double mutability, is a bug waiting to happen.
Making the Country class immutable, is probably the right decision, since the Id=>Name mapping is fixed.
I'd use:
public class County
{
public short? ID { get; private set; }
public string Name { get; private set; }
private Country(short? id,string name)
{
ID=id;
Name=name;
}
}
Lukazoid gives a good hint why not to do this, bus in fact, the Initialization you are showing would work well. You could have proofen this rather easy using your Debugger. What is the question?
Create a Country object so it is clear what that short and string are supposed to represent.