I am currently struggling with some mapping properties on my models. Here are my two models.
What I am looking to do is only have unique PersonTypes (ie MD, Nurse) in my table and the person model reference these personTypes.
public partial class Person
{
public Person()
{
this.PersonTypes = new List<PersonType>();
this.Contacts = new List<Contact>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int FacilityId { get; set; }
[DataType(DataType.Text), MaxLength(200), Required]
public string FirstName { get; set; }
[DataType(DataType.Text), MaxLength(200)]
public string MiddleName { get; set; }
[DataType(DataType.Text), MaxLength(200), Required]
public string LastName { get; set; }
public int? SpecialtyId { get; set; }
public bool IsEnabled { get; set; }
// Mapped Properties
[ForeignKey("FacilityId")]
public virtual Facility Facility { get; set; }
[ForeignKey("SpecialtyId")]
public virtual Specialty Specialty { get; set; }
public virtual ICollection<PersonType> PersonTypes { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
public partial class PersonType
{
public PersonType()
{
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[DataType(DataType.Text), MaxLength(200), Required]
public string Name { get; set; }
public bool IsEnabled { get; set; }
}
Person1 = MD, Nurse - Person2 = MD - Person3 = Nurse, CNP
I don't want to have MD in my PersonType Table 2 times from above example. Is this possible. Thanks.
From your example I gather that you have many-to-many relationship between Persons and PersonTypes. For EF CodeFirst to understand this you have to create symmetric navigation property in you PersonType: public virtual ICollection<Person> Persons.
Related
I need to pass two models in the same view, however some elements have the same name.
I have two models Employee and HolidayRequestForm and I need to use both of these in the one view which will be a details page for each Employee.
Here is my Employee:
public partial class Employee
{
public int EmployeeID { get; set; }
public string FullName { get; set; }
public string EmailID { get; set; }
public string Password { get; set; }
public System.DateTime StartDate { get; set; }
public int RoleID { get; set; }
public int ShiftID { get; set; }
public int AreaID { get; set; }
public int DisciplineID { get; set; }
public int SiteID { get; set; }
public int ALCategory { get; set; }
public Nullable<int> HoursTaken { get; set; }
public Nullable<int> AwardedLeave { get; set; }
public Nullable<int> TotalHoursThisYear { get; set; }
public int HoursCarriedForward { get; set; }
public Nullable<int> EntitlementRemainingThisYear { get; set; }
public string Comments { get; set; }
}
Here is my HolidayRequestForm:
public partial class HolidayRequestForm
{
public int RequestID { get; set; }
public int EmployeeID { get; set; }
public System.DateTime StartDate { get; set; }
public System.DateTime FinishDate { get; set; }
public int HoursTaken { get; set; }
public string Comments { get; set; }
public int YearCreated { get; set; }
public int MonthCreated { get; set; }
public Nullable<int> DayCreated { get; set; }
public Nullable<int> YearOfHoliday { get; set; }
}
I have tried Creating a separate model that contains all elements to use in the view but I'm not sure how to differentiate elements with the same name eg. Comments Is it even possible to do so?
I would like to use both these models in my view as I'd like to create an Employee Profile page, with their info on the top displaying information about their profile and then holidays they have requested using the holidayrequestform in a table on the bottom of the page.
Write a ViewModel which will contain both Employee and HolidayRequestForm as follows and then pass the ViewModel to the view:
public class EmployeeViewModel
{
public Employee Employee {get; set;}
public HolidayRequestForm HolidayRequestForm {get; set;}
}
Then in your action method:
public ActionResult EmployeeDetails(int id)
{
Employee employee = _dbContext.Employees.FirstOrDefault(emp => emp.EmployeeID == id);
HolidayRequestForm holidayRequestForm = _dbContext.HolidayRequestForms.FirstOrDefault(hrf => hrf.EmployeeID == id);
EmployeeViewModel employeeViewModel = new EmployeeViewModel()
{
Employee = employee,
HolidayRequestForm = holidayRequestForm
}
return View(employeeViewModel);
}
Then in the view, access the model properties as follows:
#model EmployeeViewModel
<p>Full Name: #Model.Employee.FullName</p>
I've a problem in customize view in my application that upload images
i have three models
public int EmpId { get; set; }
public string EmployeeName { get; set; }
public virtual ICollection<Picture> picture{ get; set; }
and second
public int MacId { get; set; }
public string machine { get; set; }
and third
public int PicId { get; set; }
public string PicPath { get; set; }
public int MacId { get; set; }
public int EmpId { get; set; }
public virtual Employee Employee { get; set; }
and i want to make it show picture of mac and who is the employee who take it ?
Create New Model With the neccesary properties you want to bind to your view.
for eg:
class newModelName
{
public Model1TypeName model1 {get ; set; }
public Model2TypeName model2 {get ; set; }
public Model3TypeName model3 {get ; set; }
}
Now you can bind this new model to your view which will have all necessary information from all the three views.
I have read this great Q&A and I tried to make something similar. My Model classes are:
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<Course> CoursesAttending { get; set; }
public Person()
{
this.CoursesAttending = new List<Course>();
}
}
public class Course
{
public int CourseId { get; set; }
public string Title { get; set; }
public ICollection<Person> Students { get; set; }
}
public class PersonCourse
{
[Key, Column(Order = 0)]
public int PersonID { get; set; }
[Key, Column(Order = 1)]
public int CourseID { get; set; }
public virtual Person Student { get; set; }
public virtual Course StudentCourse { get; set; }
public int Mark { get; set; }
public string Comment { get; set; }
}
public class SchoolContext : DbContext
{
public DbSet<Course> Courses { get; set; }
public DbSet<Person> People { get; set; }
public DbSet<PersonCourse> PersonCourseLinks { get; set; }
public SchoolContext()
: base("ManyToManyTest")
{
}
}
Now, I try to add a new person and add a new course to his courses list:
[HttpPost]
public ActionResult Create(Person person)
{
if (ModelState.IsValid)
{
Course studentCourse;
try
{
studentCourse = db.Courses.ToList<Course>().First();
}
catch
{
studentCourse = new Course() { Title = "HTML" };
}
person.CoursesAttending.Add(studentCourse);
db.People.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(person);
}
Everything goes well, but when I open my created database, I see there are 2 link tables for the Person and Course classes - PersonCourses(with fields: PersonID, CourseID, Mark, Comment) and PersonCourse1(with fields: PersonID, CourseID), and only PersonCourse1 has rows (actually one row). Why does it happen? Did I do something not correct? I expect to see only one link table - the PersonCourses table...
I expect to see only one link table - the PersonCourses table
Then you have to link PersonCourse entity with Person entity though CoursesAttending navigational property. Same thing has to be done to Course entity.
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<PersonCourse> CoursesAttending { get; set; }
public Person()
{
this.CoursesAttending = new List<PersonCourse>();
}
}
public class Course
{
public int CourseId { get; set; }
public string Title { get; set; }
public ICollection<PersonCourse> Students { get; set; }
}
Give foreign key associations to the foreign key properties in your gerund table:
public class PersonCourse
{
[Key, Column(Order = 0)]
public int PersonID { get; set; }
[Key, Column(Order = 1)]
public int CourseID { get; set; }
[ForeignKey("PersonID")]
public virtual Person Student { get; set; }
[ForeignKey("CourseID")]
public virtual Course StudentCourse { get; set; }
public int Mark { get; set; }
public string Comment { get; set; }
}
Just so you now why your code wasn't working as expected:
public class PersonCourse
{
[Key, Column(Order = 0)]
public int PersonID { get; set; }
[Key, Column(Order = 1)]
public int CourseID { get; set; }
public virtual Person Person { get; set; } // Follow built in conventions
public virtual Course Course { get; set; }
public int Mark { get; set; }
public string Comment { get; set; }
}
This now follows the built in Entity Framework convention of having
public int [ClassName][Id] or [Id] //Database Foreign Key column
and
public NavigationProperty [ClassName] // Navigation Property
I'm building website in MVC 3.
i am using EF code first in existing database.
my ET inside the model look like that:
public class Pages
{
[Required]
public int ID { get; set; }
public int ParentID { get; set; }
[Required]
public int PageType { get; set; }
[Required]
[DataType(DataType.Text)]
[DisplayName("כותרת")]
public string Title { get; set; }
public string SearchWords { get; set; }
public string Leng { get; set; }
public int? Sort { get; set; }
public string Modules { get; set; }
[ForeignKey("PageType")]
public virtual PagesType Type { get; set; }
public virtual IEnumerable<PagesType> Types { get; set; }
[ForeignKey("PageID")]
public ICollection<PageContent> PageContent { get; set; }
[ForeignKey("PageID")]
public virtual ICollection<ImagesTable> Images { get; set; }
}
public class PageContent
{
public int ID { get; set; }
public int PageID { get; set; }
public string Header { get; set; }
public string Text { get; set; }
[ForeignKey("ID")]
public virtual ICollection<Pages> Pages { get; set; }
}
as you see in my fist table that cold Pages i have a relationship to another table that named PageContent.
in my Pages class i had this code
[ForeignKey("PageID")]
public ICollection<PageContent> PageContent { get; set; }
now, when i trying to add new pageContent into new page i get an error.
see this code
public ActionResult AddPage(PageModel page)
{
SystemLogic cmd = new SystemLogic();
page.Leng = "he";
Models.Pages p = new Pages();
p.ParentID = page.ParentID;
PageContent pageContent = new PageContent();
pageContent.Text = page.Content;
p.PageContent.Add(pageContent);
The error is
Object reference not set to an instance of an object.
What i did wrong?
You will get the NRE at p.PageContent.Add(pageContent); because the collection is not initialized. Initialize the collections inside the constructor of Pages class.
public class Pages
{
public Pages()
{
PageContent = List<PageContent>();
Images = List<ImagesTable>();
}
[Required]
public int ID { get; set; }
public int ParentID { get; set; }
[Required]
public int PageType { get; set; }
[Required]
[DataType(DataType.Text)]
[DisplayName("כותרת")]
public string Title { get; set; }
public string SearchWords { get; set; }
public string Leng { get; set; }
public int? Sort { get; set; }
public string Modules { get; set; }
[ForeignKey("PageType")]
public virtual PagesType Type { get; set; }
public virtual IEnumerable<PagesType> Types { get; set; }
[ForeignKey("PageID")]
public ICollection<PageContent> PageContent { get; set; }
[ForeignKey("PageID")]
public virtual ICollection<ImagesTable> Images { get; set; }
}
Or before you add objects to the collection
if (p.PageContent == null) p.PageContent = new List<PageContent>();
p.PageContent.Add(pageContent);
You should consider using proper naming conventions(eg Page instead of Pages).
i have got on my DB 3 tables
movies, workers, workermovies ( this is the Relationship table )
public class Movie
{
public Movie()
{
Genres = new List<Genre>();
Formats = new List<Format>();
ProductionCompanies = new List<ProductionCompany>();
Workers = new List<Worker>();
}
public int Id { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string StoryLine { get; set; }
public int RunTime { get; set; }
[ForeignKey("MPAARateId")]
public MPAARate MPAARate { get; set; }
public int MPAARateId { get; set; }
public byte[] ImageData { get; set; }
public string ImageMimeType { get; set; }
public DateTime CreatedDate { get; set; }
public string OfficialSite { get; set; }
public int Budget { get; set; }
public int StatusId { get; set; }
public virtual ICollection<Genre> Genres { get; set; }
public virtual ICollection<Format> Formats { get; set; }
public virtual ICollection<ProductionCompany> ProductionCompanies { get; set; }
public virtual ICollection<Worker> Workers { get; set; }
}
public class Worker
{
public int Id { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public DateTime Birthday { get; set; }
public string Biography { get; set; }
public string BornName { get; set; }
public double Height { get; set; }
public DateTime? Died { get; set; }
public byte[] ImageData { get; set; }
public string ImageMimeType { get; set; }
public bool IsActor { get; set; }
public bool IsDirector { get; set; }
public bool IsWriter { get; set; }
public bool IsProducer { get; set; }
public bool IsStar { get; set; }
public virtual ICollection<Movie> Movies { get; set; }
}
in this Relation i got the movieId and the workerId
but i also got some more fields if the person acted or writen or producer etc.
how do i define the relation entity class if needed
and when i want to get just the ppl that acted in the movie how do i wrote such a linq
query
You need to introduce an additional entity in your model WorkerMovie and convert the many-to-many relationship between Worker and Movie into two one-to-many relationships - one between Worker and WorkerMovie and the other between Movie and WorkerMovie. A sketch:
public class WorkerMovie
{
[Key, Column(Order = 0)]
public int WorkerId { get; set; }
[Key, Column(Order = 1)]
public int MovieId { get; set; }
public Worker Worker { get; set; }
public Movie Movie { get; set; }
public bool WorkedAsActor { get; set; }
public bool WorkedAsWriter { get; set; }
public bool WorkedAsProducer { get; set; }
// etc.
}
public class Movie
{
// ...
public virtual ICollection<WorkerMovie> WorkerMovies { get; set; }
// remove ICollection<Worker> Workers
}
public class Worker
{
// ...
public virtual ICollection<WorkerMovie> WorkerMovies { get; set; }
// remove ICollection<Movie> Movies
}
If you want only to find the workers who were actors in a particular movie with a movieId you can write:
var workersAsActors = context.WorkerMovies
.Where(wm => wm.MovieId == movieId && wm.WorkedAsActor)
.Select(wm => wm.Worker)
.ToList();
Here is another answer to a very similar question with many more examples of possible queries: Create code first, many to many, with additional fields in association table