multiple "1 to 0..1" relationship models - asp.net-mvc

I am using this tutorial from microsoft to create a one-zero-to-one relationship with EF4.1 Between an Instructor and OfficeAssignment. This is working like a charm.
But now I want to add a Home for each Instructor (1 to zero-or-1) like in this:
I added the Home model exactly the same way as the OfficeAssignment (like in the tutorial above), but when I try to add controllers for these model, I get the error "An item with the same name has already been added".
So my model is set up incorrectly.
What is wrong with the below?
How do I create multiple one-to-zero-to-one relationships in EF4.1?
public class Instructor
{
public Int32 InstructorID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public virtual OfficeAssignment OfficeAssignment { get; set; }
public virtual Home Home { get; set; }
}
public class OfficeAssignment
{
[Key]
public int InstructorID { get; set; }
public string Location { get; set; }
public virtual Instructor Instructor { get; set; }
}
public class Home
{
[Key]
public int InstructorID { get; set; }
public string Location { get; set; }
public virtual Instructor Instructor { get; set; }
}
public class Context : DbContext
{
public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
public DbSet<Instructor> Instructors { get; set; }
public DbSet<Home> Homes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Instructor>()
.HasOptional(p => p.OfficeAssignment)
.WithRequired(p => p.Instructor);
modelBuilder.Entity<Instructor>()
.HasOptional(p => p.Home).WithRequired(p => p.Instructor);
}

Doesn't look like EF supports real 1 to 0..1 relationship. You need a foreign key. And add the optional (int?) into the main model.
So I did this as follow, and it works like a charm.
public class Instructor
{
public Int InstructorID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public int? OfficeAssignmentID { get; set; }
public virtual OfficeAssignment OfficeAssignment { get; set; }
public int? HomeID { get; set; }
public virtual Home Home { get; set; }
}
public class OfficeAssignment
{
public int OfficeAssignmentID { get; set; }
public string Location { get; set; }
}
public class Home
{
public int HomeID { get; set; }
public string Location { get; set; }
}

Related

posting customer details with 'n ' no of address

I have two model classes "customerdetails" and "addresssdetails".my question is "one customer can save with multiple addresss?
namespace customer2.Models
{
public class customerdetails
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { set; get; }
[Key]
public int customerid { set; get; }
public string customername { set; get; }
}
public class addressdetails
{
public int addressno { set; get; }
public string street { set; get; }
public string landmark { set; get; }
public int pincode { set; get; }
}
public class MkContext : DbContext
{
public virtual DbSet<customerdetails> customers { get; set; }
public virtual DbSet<addressdetails> address { get; set; }
}
public class customerviewmodel
{
public customerdetails cd { set; get; }
public List<addressdetails> ad { set; get; }
}
}![enter image description here](https://i.stack.imgur.com/4QCA1.jpg)
Before I answer, just a quick tip:
Make sure to properly case your class names and properties to improve readability.
Here is a link with some guidelines
If you want to store a Customer with multiple AddressDetails, you will need to define a class and add it to the context.
public class Customer {
public int Id { get; set; }
public CustomerDetails CustomerDetails { get; set; }
public IList<AddressDetails> AddressDetails { get; set; }
}
Then add this to the context.

Asp.Net MVC Codefirst Model Relation to the Same Model

I have a model and i want to put an extra field which can be populated form the same model. IE: Categories and and sub-categories.
In my example, visitor can add an filetype but if file type is under an another file type, he can choose,
But i cant work it out. Below you can see my model.
public class HrFileType
{
[Key]
public int Id { get; set; }
[Display(Name = "Dosya Adı")]
public int Name { get; set; }
public int? HrFileTypeId { get; set; }
public virtual HrFileType HrFileType2 { get; set; }
}
You just need to add a ForeignKeyAttribute like below:
public class HrFileType
{
[Key]
public int Id { get; set; }
[Display(Name = "Dosya Adı")]
public int Name { get; set; }
public int? HrFileTypeId { get; set; }
[ForeignKey("HrFileTypeId")]
public virtual HrFileType HrFileType2 { get; set; }
}
You can also use fluent API to achieve this:
public class HrFileType
{
[Key]
public int Id { get; set; }
[Display(Name = "Dosya Adı")]
public int Name { get; set; }
public int? HrFileTypeId { get; set; }
public virtual HrFileType HrFileType2 { get; set; }
}
public class YourDbContext : DbContext
{
public DbSet<HrFileType> HrFileTypes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//
modelBuilder.Entity<HrFileType>()
.HasOptional(c => c.HrFileType2)
.WithMany()
.HasForeignKey(c => c.HrFileTypeId);
}
}
Have you tried listing the other file types?
public class HrFileType
{
[Key]
public int Id { get; set; }
[Display(Name = "Dosya Adı")]
public int Name { get; set; }
public List<HrFileType> RelatedTypes { get; set; }
}
then using Entity Frameworks fluent API in the DbContext, try explicitly declaring a many to many map.
modelbuilder.Entity<HrFileType>().HasMany(x => x.RelatedTypes).WithMany();
I'd be very interested to see if this works. It's the only logical solution I can think of without having some kind of parent class.

Entity Framework Fluent API

My Entities are as follows...
public class Project{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Survey> Surveys { get; set; }
}
public class Survey{
public int Id { get; set; }
public int ProjectId { get; set; }
public string Name { get; set; }
public virtual Project Project { get; set; }
}
public class Category{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Survey> Surveys { get; set; }
}
public class SurveyCategory{
public int Id { get; set; }
public int SurveyId{ get; set; }
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual Survey Survey { get; set; }
public virtual Category Category { get; set; }
}
A project will have list of Surveys, A Survey will have only one Category, A Category can have multiple Survey, SurveyCategory is the table where I am storing Survey + Category link.
Can anyone direct me to what would be appropriate Fluent API code will be for this to map properly.... So far I have this....
protected override void OnModelCreating(DbModelBuilder modelBuilder){
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Project>().HasMany(project => project.Surveys);}
hi I hope I understood what you are looking for.
First of al you should do a few changes to your model
public class Project
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Survey> Surveys { get; set; }
}
public class Survey
{
public int Id { get; set; }
public int ProjectId { get; set; }
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual Project Project { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<SurveyCategory> SurveyCategory { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Survey> Surveys { get; set; }
public virtual ICollection<SurveyCategory> SurveyCategory { get; set; }
}
public class SurveyCategory
{
public int Id { get; set; }
public string Name { get; set; }
public int SurveyId { get; set; }
public virtual Survey Survey { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
And then on the model creating you should do this
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Project>()
.HasMany(p => p.Surveys)
.WithRequired(u => u.Project);
modelBuilder.Entity<Category>()
.HasMany(p => p.Surveys)
.WithRequired(u => u.Category);
modelBuilder.Entity<Category>()
.HasMany(p => p.SurveyCategory)
.WithRequired(u => u.Category)
.HasForeignKey(k => k.CategoryId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Survey>()
.HasMany(p => p.SurveyCategory)
.WithRequired(u => u.Survey)
.HasForeignKey(k => k.SurveyId)
.WillCascadeOnDelete(false);
}
I hope this helps

EF Many to Many Relationship on 3 Tables(Fluent API)

I have 3 tables that needs to be combined in one table. On below you can see the codes.
The problem is each player could play on one or more team on each tournament. Players and teams arranger by every new tournament.
So how can i map it with fluent api or maybe there is a better way to solve it. Thanks from now on.
public class Player
{
public int PlayerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public DateTime TimeStamp { get; set; }
public ICollection<Team> Teams { get; set; }
public ICollection<Tournament> Tournaments { get; set; }
}
public class Team
{
public int TeamID { get; set; }
public string Name { get; set; }
public DateTime TimeStamp { get; set; }
public ICollection<Player> Players { get; set; }
public ICollection<Tournament> Tournaments { get; set; }
}
public class Tournament
{
public int TournamentID { get; set; }
public DateTime Date { get; set; }
public int PlaceID { get; set; }
public DateTime TimeStamp { get; set; }
public virtual Place Place { get; set; }
public ICollection<Player> Players { get; set; }
public ICollection<Team> Teams { get; set; }
}
public class BPContext : DbContext
{
public DbSet<Tournament> Tournaments { get; set; }
public DbSet<Place> Places { get; set; }
public DbSet<Table> Tables { get; set; }
public DbSet<Player> Players { get; set; }
public DbSet<Team> Teams { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
I don't see what are you trying to accomplish with this. You have tables that contain all players, all teams and all tournaments.
I suppose there will be a match to be played? What you can do is create another table Matches, to use entity similar to this:
public class Match
{
[Key]
public int MatchId {get;set;}
[ForeignKey("Tournament")]
public int TournamentId {get;set;}
[InverseProperty("Matches")]
public virtual List<Team> Teams {get;set;}
[InverseProperty("Matches")]
public virtual List<Player> Players {get;set;}
[InverseProperty("Matches")]
public virtual Tournament Tournament {get;set;}
}
This new entity holds all 3 previous entities. However you have to modify previous ones to include these changes:
public class Player
{
public int PlayerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public DateTime TimeStamp { get; set; }
[InverseProperty("Players")]
public virtual List<Match> Matches { get; set; }
[InverseProperty("Players")]
public virtual List<Team> Teams {get;set;}
}
Getting all tournaments for player can be done with LINQ : ctx.Players.Where(x => x.PlayerId == 15).Matches.Select(x => x.TournamentId).
If you want to see all the players in a tournament: ctx.Matches.Where(x => x.TournamentId ==15).Players.Select(x => x.Name).
public class Team
{
public int TeamID { get; set; }
public string Name { get; set; }
public DateTime TimeStamp { get; set; }
[InverseProperty("Teams")]
public List<Match> Matches {get;set;}
[InverseProperty("Teams")]
public List<Player> Players {get;set;}
}
public class Tournament
{
public int TournamentID { get; set; }
public DateTime Date { get; set; }
public int PlaceID { get; set; }
public DateTime TimeStamp { get; set; }
public virtual Place Place { get; set; }
[InverseProperty("Tournament")]
public virtual List<Match> Matches {get;set;}
}

EF Code First giving problems in foreign keys

public class ParikshaContext :DbContext
{
public ParikshaContext()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<ParikshaContext>());
}
public DbSet<UserDetail> UserDetails { get; set; }
public DbSet<Standard> Standards { get; set; }
public DbSet<Subject> Subjects { get; set; }
public DbSet<QuestionDescriptor> QuestionDescriptors { get; set; }
public DbSet<QuestionBrief> QuestionBriefs { get; set; }
public DbSet<QuestionCustom> QuestionCustoms { get; set; }
public DbSet<QuestionChoice> QuestionChoices { get; set; }
public DbSet<QuestionMatch> QuestionMatches { get; set; }
public DbSet<Test> Tests { get; set; }
public DbSet<Test_Question> Test_Questions { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<QuestionCustom>().ToTable("Custom");
modelBuilder.Entity<QuestionBrief>().ToTable("Brief");
modelBuilder.Entity<QuestionMatch>().ToTable("Match");
modelBuilder.Entity<QuestionChoice>().ToTable("Choice");
}
}
public class QuestionDescriptor
{
public int QuestionDescriptorId { get; set; }
public int StandardId { get; set; }
[ForeignKey("StandardId")]
public virtual Standard Standard { get; set; }
public int SubjectId { get; set; }
[ForeignKey("SubjectId")]
public virtual Subject Subject { get; set; }
public int Rating { get; set; }
public int Difficulty { get; set; }
public DateTime DateOfCreation{get;set;}
public int UserDetailId { get; set; }
[ForeignKeyAttribute("UserDetailId")]
public virtual UserDetail Creator { get; set; }
}
public class QuestionBrief : QuestionDescriptor
{
public String QuestionText { get; set; }
public String Answer { get; set; }
//true for fill in the blanks and false for a loing answers
public bool Short { get; set; }
}
public class Standard
{
public int StandardId { get; set; }
public String StandardName { get; set; }
}
public class Subject
{
public int SubjectId { get; set; }
public String SubjectName { get; set; }
public String SubjectCategory { get; set; }
// public int StandardId { get; set; }
// [ForeignKey("StandardId")]
// public virtual Standard Standard { get; set; }
}
public class Test
{
public int TestID { get; set; }
public DateTime DateOfCreation { get; set; }
public String StandardName { get; set; }
public String SubjectName { get; set; }
public String SubjectCategory { get; set; }
// public int UserDetailId { get; set; }
// [ForeignKey("UserDetailId")]
// public virtual UserDetail Creator { get; set; }
}
public class Test_Question
{
public int Test_QuestionID { get; set; }
public int TestId { get; set; }
[ForeignKey("TestId")]
public virtual Test Test { get; set; }
public int QuestionDescriptorId { get; set; }
[ForeignKey("QuestionDescriptorId")]
public virtual QuestionDescriptor Question { get; set; }
}
public class UserDetail
{
public int UserDetailId { get; set; }
[Required]
[MaxLength(10, ErrorMessage = "UserName must be 10 characters or less"), MinLength(5)]
public String Name { get; set; }
[Required]
public String Password { get; set; }
public String UserRole { get; set; }
public DateTime DateOfCreation{ get; set;}
}
//Match,Custom,Choice classes have been omitted for lack of space (which sounds stupid when i look at the amount of code i have pasted )
I have two problems:-
I cant get a foreign key relation between standard and subjects,it says the relation will cause several cascade delete paths...
if I make a foreign key rlation between test and usedetail it gives me the above problem for mapping the tst_question table .
Also since I am new to EF code first ,please point out my mistakes.all help and disccussion is welcome.
By default EF will create foreign keys will cascade delete. In your model if you delete a Standard there are multiple paths to delete the QuestionDescriptor.
Standard -> QuestionDescriptor
and
Standard -> Subject -> QuestionDescriptor
That is why SQL server does not allow you to do this. See this answer for more details
What you can do is explicitly tell EF to create foreign keys without cascade delete. But this may create data integrity problems. So make sure you understand the consequences.
What you can do is configure the relationships using fluent API with WillCascadeOnDelete(false).
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//other mappings
modelBuilder.Entity<Subject>()
.HasRequired(subject => subject.Standard).WithMany()
.HasForeignKey(subject => subject.StandardId)
.WillCascadeOnDelete(false);
}

Resources