Modeling a one-to many relationship- Model vs ViewModel - c#

I am currently trying to model an object class with a one-to-many relationship with another object in Model-First MVC- a "Contact" object that includes, among other things, a list of (references to?) one or more "Interests", chosen upon creation of a Contact from the full database list of Interests. It is my understanding that one uses a ViewModel to accommodate such a relationship, but I think I am misunderstanding what does or does not go in the model vs the viewModel.
At present, I have a Contacts model:
public class Contact
{
public int Id { get; set; }
public string Email { get; set; }
public virtual List<Interest> Interests { get; set; }
public List<int> InterestIds { get; set; }
}
An Interest model:
public class Interest
{
public int Id { get; set; }
public string Name { get; set; }
}
A Contact viewModel:
public class ContactViewModel
{
public int Id { get; set; }
public string Email { get; set; }
public List<int> InterestIds { get; set; }
public List<InterestViewModel> Interests { get; set; }
}
And an Interest viewModel
public class ContactViewModel
{
public int Id { get; set; }
public string Email { get; set; }
public List<int> InterestIds { get; set; }
public List<InterestViewModel> Interests { get; set; }
}
But I'm getting conflicted accounts of what goes where.
In short, I intend the end result that I should be able to choose one or more Interests (preferably with a series of checkboxes) from the Create view to be stored in the new Contact, and then from the Index view be able to filter the table of Contacts by which Interests they do or do not have. I have logic planned out for most of that already, but for the time being how should I design my Models vs my ViewModels in order to best accommodate this vision?

your Contact entity has a logical error, you should remove InterestIds property from Contact entity and add a property with name ContactId to your Interest entity. it provides foreign key for contact(one to many relation from Contact to Interest). however if ViewModel is equals to the Model, so you don't need any ViewModel.

Related

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

Using ICollection with MVC & Entity framework

Hi I'm learning to use MVc using Code first method. I'm having trouble understanding the use of ICollection<> with my setup. I have two classes/entitys: 'Restaurant' & 'RestaurantReview' as below:
public class Restaurant
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
public string Country { get; set; }
public ICollection<RestaurantReview> Reviews { get; set; }
}
and.....
public class RestaurantReview
{
public int Id { get; set; }
public int Rating { get; set; }
public string Body { get; set; }
public string ReviewerName { get; set; }
public int RestaurantId { get; set; }
}
now whats confusing me is the last property of the Restaurant class. Why is it of type 'ICollection' and uses my RestaurantReview class as a parameter, what does it do, hope I
have made myself clear
It's a definition of one to many relationship.
With that property (sometimes called Navigation Property) Entity Framework will be able to connect Review with Restaurant it was written about. It will also allow you to get Review entities for given Restaurant entity really easily.
You can also remove public int RestaurantId { get; set; } from RestaurantReview class - That column is gonna be generated automatically by EF because of ICollection<RestaurantReview> in Restaurant class.

Scaffold to dropdown list with C# EF4 - code first

I'm using C#.NET, Entity Framework 4.1 and the code first approach. From that i have a bunch of entities and one entity is related to another entity. They have a primary key/foreign key relation.
I'm also using ViewModels to specify which attributes may be scaffolded and i was hoping that the two related entities would create a dropdown list. But that's not happening.
This is just an example of how my entity relation looks, to illustrate my problem.
UserType entity:
public class UserType
{
public int UserTypeID { get; set; }
public string Type { get; set; }
public virtual ICollection<User> Users { get; set; }
}
User entity:
public class User
{
public int UserID { get; set; }
public int UserTypeID
public string Username { get; set; }
public bool IsAdmin { get; set; }
public virtual UserType UserType { get; set; }
}
My ViewModel:
[JsonObject(MemberSerialization = MemberSerialization.OptOut, IsReference = false)]
[DataContract]
public class UserViewModel : BaseViewModel
{
[Key]
public int UserID { get; set; }
public int UserTypeID { get; set; }
[required]
public string Username { get; set; }
}
So the UserViewModel is scaffolded. And i want it to create a dropdown list for the UserType. But right now it only creates an input field for UserTypeID. How can i make it show a dropdown list with the values of UserTypes?
The scaffolder has no idea that UserTypeId in your view model relates to an actual UserType class, and therefore has no way of knwoing where to get the static list of user types from.
If you look at the example you referenced, it also includes a navigation property to the foreign key class.

Categories