Scaffolding entity relationships with MVC5 EF6 - asp.net-mvc

Im learning MVC 5 with Entity Framework 6. How can i make the model support relationships between my classes. Like a one Employee can have several Tasks. Is it possible to make the scaffolding set it up automagically?
Ive read some similar tutorials for earlier versions but they dont seem to apply. So i ask for answers from someone who has experience of MVC5 with EF6.

Without any code to base this on, here's all you really have to do to set up a one-to-many relationship in EF6:
public class Employee
{
public int ID { get; set; }
public string name { get; set; }
public List<Task> Tasks { get; set; }
}
public class Task
{
public int ID { get; set; }
public string Title { get; set; }
public Employee AssignedEmployee { get; set; } //Not required, but it would be nice to easily access the owner of a task from code.
[ForeignKey("AssignedEmployee ")]
public int EmployeeID { get; set; } //Also not required, but comes in handy often. Just holds the ID of the assigned employee. I always include this, but it's just a preference.
}
Just remember to add these to classes as properties to your EF context. This is a simple example, since you're not very specific with what you want to achieve. :)

Related

How to design EF core code-first database when different tables share the same fields

I'm working on a ASP .NET Core 5 MVC application with MS-SQL database and EF Core is my ORM (with the code-first approach).
Currently I'm redesigning the database, I have multiple tables that share a lot of the same properties, and I want to be able to add/remove properties from different tables, but only in one place in the code.
Because .NET doesn't have multiple class inheritance, I came up with the idea to inherit the classes in "levels".
Basically, in the example below, the purchases table and the products table should have exactly the same prices, dates and content properies, but also some additional specific fields:
class Purchase : PriceDatesAndContent
{
// specific purchase properties
}
class Product : PriceDatesAndContent
{
// specific product properties
}
class PricesDatesAndContent : PriceAndDates
{
public string Name { get; set ; }
public string Description { get; set; }
}
class PricesAndDates : Prices
{
public DateTime someDate1 { get; set; }
public DateTime someDate2 { get; set; }
// ...
}
class Prices
{
public double Price1 { get; set; }
public double Price2 { get; set; }
}
However, I'm not really sure that this is really a brilliant idea as it seems to me, I would love to hear your opinion, or maybe you even have another workaround for this scenario?
Thank you very much!
However, I'm not really sure that this is really a brilliant idea as it seems to me
Having a deep inheritance hierarchy is fine so long as your base classes aren't mapped as Entities. But it is unusual to model your classes this way just to save yourself a bit of typing.
It would probably be better to use interfaces to model the common property patterns, so you don't have to arrange them in a single hierarchy. eg
public interface IHasName
{
public string Name { get; set; }
public string Description { get; set; }
}
public interface IHasPrices
{
public double Price1 { get; set; }
public double Price2 { get; set; }
}

Entity Framework - Map N:N relation with extra field with Fluent API

I'm trying to map a relation N:N for an entity which has some other information. In fact, to brief you better I have the following scenario:
A user can apply as many times as he wants for a exam and this application saves the final result. (That's why i didn't map the key with this to classes)
Looking for this over the internet I found some solutions regarding the creation of Id properties to save information about the Foreign Key besides the property itself. As I don't agree with this solution because I don't believe that we have to change our Model to satisfy ORM needs, I would like to know if you guys have another solution for me.
The following code is a piece of the classes I want to map. Currently, I didn't configure collections in the main classes and when I try to save the application I receive a key violation in the database because it tries to save the User/Exam in the database again.
Sorry if it is a silly question and thanks for your help.
public class User
{
public int Id { get; set; }
public string FullName { get; set; }
}
public class Exam
{
public int Id { get; set; }
public string Description { get; set; }
}
public class Application
{
public int Id { get; set; }
public virtual User User { get; set; }
public virtual Exam Exam { get; set; }
public int Result { get; set; }
}

how to scaffold more then one class with foreign key in mvc 5?

Is it possible to scaffold more then one class in MVC 5?
I have 2 classes I'd like to been able to edit/create on one page.
Do I have to scaffold separately each class and then connect somehow their views or is there a better way? Let say I have classes Office and Contacts
and want Office data and Contacts for that office to be editable on one page.
Also I do code first approach and not sure how to connect them with foreign key? One office can have many contacts. I have classes as below
thanks
public class Office
{
[Key]
public int Id { get; set; }
public int ContactId { get; set; }
public string OfficeName { get; set; }
}
public class Contact
{
[Key]
public int Id { get; set; }
public int OfficeId { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
}
It sounds like this would be a good time to use a View Model. Scaffolding is a great way to quickly create views for a given model, but at some point you've got to introduce more robust models to handle scenarios like what you've described. Create another model class (or 'view model' class if you've delegated a folder for those) such as
namespace MyProject.Web.ViewModels
{
public class OfficeContactsVModel
{
public Office OfficeModel { get; set; }
public Contact ContactModel { get; set; }
}
}
Of course, if you are using repository pattern it'll have to be hooked up differently. You could also specify a custom model with values you need for your form and map them to a specific model in a post ActionResult in the controller. There are plenty of ways to achieve what you are looking for.
(Also see: Multiple models in a view and ASP.NET MVC 5 - Scaffolding for Many to One Relationship)

CRUD Views For Many-Many Relationship, Checkboxes

I am having a hard time trying to figure out what I need to do to get this to work. I'm learning ASP.NET MVC CodeFirst with EF. If I make a model I can simply add a controller for that model and add scaffolding to create views that automatically take care of CRUD. But now I have two models, Project and Category. They have a many to many relationship and database is designed correctly with the associative table without having to make a separate model for it. The code for the models is this....
public class Project
{
public int ProjectId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Testimonial { get; set; }
public virtual ICollection<Image> Images { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public Project()
{
Categories = new HashSet<Category>();
}
}
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public ICollection<Project> Projects { get; set; }
public Category()
{
Projects = new HashSet<Project>();
}
}
So I add my controllers and do the scaffolding. I go in and create my categories just fine. But when it comes to my Projects/Create view, I would like to make it so that all the categories are displayed as checkboxes. Also, I would like to ensure that at least one category is selected before being able to submit the form to create a project. How would I do this?
For an example of using check boxes in a similar scenario, see Adding Course Assignments to the Instructor Edit Page in this tutorial:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/updating-related-data-with-the-entity-framework-in-an-asp-net-mvc-application

Custom Conditional validation on strongly typed view in MVC

I have a Person model and a student model. The student model has 2 FKs of PersonIDs; one for student and the other for parent.
My view looks like this:
#Html.EditorFor(m => m.student.Person.FirstName)
#Html.EditorFor(m => m.student.Person.DOB)
#Html.EditorFor(m => m.student.Father.FirstName)
The models would look like this:
public partial class Person
{
public int PersonID { get; set; }
[Required]
[PlaceHolder("First Name")]
public string FirstName { get; set; }
[PlaceHolder("Birth Date")]
public Nullable<System.DateTime> DOB { get; set; }
}
public partial class Student
{
public int Student_PersonID { get; set; }
public int Parent_PersonID { get; set; }
}
I want the DOB to be required field for the student but not for the parent. If I add [Required] attribute to the DOB element, then it requires it for both. Is there a way I can set a require a field on the view? or is there a way in the model or using validation attribute to do this?
fyi... i am using EF database first approach
thanks
I would suggest having the view model match the fields that are displayed in the view. If later a field is to be removed from the view, then it will also be removed from the domain model.
In this case, if your view is to display the following fields:
StudentFirstName
StudentDOB
ParentFirstName
ParentDOB
Then I would suggest having the following view:
public class PersonViewModel
{
public int StudentPersonID { get; set; }
[Required]
public string StudentFirstName { get; set; }
[Required]
public DateTime StudentDOB { get; set; }
public int ParentPersonID { get; set; }
[Required]
public string ParentFirstName { get; set; }
public DateTime ParentDOB { get; set; }
}
Or if instead you have 2 seperate views displaying:
StudentFirstName
StudentDOB
AND displaying:
ParentFirstName
ParentDOB
Then I would suggest having 2 seperate view models:
public class StudentViewModel
{
public int StudentPersonID { get; set; }
[Required]
public string StudentFirstName { get; set; }
[Required]
public DateTime StudentDOB { get; set; }
}
public class ParentViewModel
{
public int ParentPersonID { get; set; }
[Required]
public string ParentFirstName { get; set; }
public DateTime ParentDOB { get; set; }
}
Using the view models in this way will allow you to use the [Required] data annotations for the fields that require them rather than trying to create a workaround. Note that the view models are not to be confused with the domain models and therefore this data would then need to be mapped to the domain model.
Hope this helps.
If your application is a simple application you may not need to create a seperate business logic layer and most books only present MVC with simple models which may be fine. However, if you search around you will find other examples where developers recommend having a view model seperate from a business model such as this
I would also recommend reading Wrox Professional Enterprise .Net 2009 where chapters 7 & 8 give great examples of the business layer with discussions of the Transaction Script pattern, Active Record pattern and Domain Model pattern.
One way is to make a PersonRequired class that inherits from Person. Add a metadata class to PersonRequired so you have PersonRequiredMetaData and in that specific that the inherited DOB field is required. You would need to manually copy the values between the Person and PersonRequired classes or use AutoMapper. I hope there is a better answer than this!
Another option is to use FluentValidation that would let you do the validation separate from the model (doesn't use data annotations). I wonder if some people are using data annotations for database requirements and fluent validation for programmatic requirements.

Resources