Change Model After Code First Migration - asp.net-mvc

I enabled Code First Migration but after sometime I changed the model properties so when i ran the application the following error is given.
Invalid column name etc...because after migration i changed the model.
So far I understand the problem is that I updated the model but these changes don't apply to database table...kindly help me to fix it..means model properties and database column don't match
Migration is enabled.
I set automatic migration to true but i doesn't work.
Error
public class Floor
{
public int FloorID { get; set; }
public string Name { get; set; }
public virtual ICollection<Room> Rooms { get; set;}
}
public class Room
{
public int RoomID { get; set; }
public string Name { get; set; }
[Display(Name ="Room Rent")]
public decimal Rent { get; set; }
[Display(Name="Floor")]
public int FloorID { get; set; }
public int Seater { get; set; }
[Display(Name="Attach Bathroom")]
public Boolean AttachedBathRoom { get; set; }
public virtual Floor Floor { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
public class Student
{
public int StudentID { get; set; }
public string Name { get; set; }
public int CNIC { get; set; }
public int Phone { get; set; }
[Display(Name="Floor")]
public int FloorID { get; set; }
[Display(Name ="Room No")]
public int RoomID { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string Department { get; set; }
public virtual Floor Floor { get; set; }
public virtual Room Room { get; set; }
}

First, you need to specify your primary and foreign keys in your classes.
To specify a primary key, add [Key] before your key attribute. For a foreign key, you also have to add the table it is linked to. So in your Room class you would have something like this:
[Key]
[ForeignKey("Floor")]
public int FloorID { get; set; }
Do the same for all your keys in all your models.
Then, you need to add a new migration and then update your database.
In your Packet Manager Console, type this to add a new migration:
Add-Migration FooBar
Then update your database with this command:
Update-Database

Related

Entity Framework Core 5 - Introducing FOREIGN KEY constraint on table may cause cycles or multiple cascade paths

I am trying to implement Entity Framework core 5
and am also new to it. below are three models that I am trying to implement.
before posting a new question, I checked the following answers but couldn't understand the card example. Maybe my problem listed below will help anyone else like me today to understand it better.
Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?
Foreign key constraint may cause cycles or multiple cascade paths?
My models are given below :
[Table("Clinics")]
public class Clinic
{
public int ClinicID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Address { get; set; }
public List<Doctor> DoctorsAvailable { get; set; } = new List<Doctor>();
}
[Table("Doctors")]
public class Doctor
{
public int ID { get; set; }
public string Name { get; set; }
public DoctorsSpecilization Specilization { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public List<Clinic> ClinicsAvailableAt { get; set; } = new List<Clinic>();
}
[Table("Patients")]
public class Patient
{
public int PatientID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public int DoctorID { get; set; }
public Doctor Doctor { get; set; }
}
[Table("Consultations")]
public class Consultation
{
public int ID { get; set; }
public int ClinicID { get; set; }
public int DoctorID { get; set; }
public int PatientID { get; set; }
public Clinic Clinic { get; set; }
[ForeignKey("DoctorID")]
public Doctor Doctor { get; set; }
[ForeignKey("PatientID")]
public Patient Patient { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
}
The problem is the navigation properties of the Doctor and Patient in the Consultation model. When I try to "update-database" it fails with
Introducing FOREIGN KEY constraint 'FK_Consultations_Patients_PatientID' on table 'Consultations' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
However, if the navigation properties are removed it works fine. You may ask why I need to have those navigation properties. It's for the sake of displaying relevant information on the view.
Any help in explaining or commenting about the concept would be very much appreciated.
Thank you.
Here are the cascade delete paths in the shown model
Clinic -> Consultation
Doctor -> Consultation
Patient -> Consultation
Doctor -> Patient -> Consultation
The problem (multiple cascade paths) are the last two. As you can see, when deleting a Doctor, the linked Consultation records can be deleted either directly or view linked Patient records. Because of that possibility, some databases (mainly SqlServer) reject cascade delete options and require you to turn of it for at least one of the relationships forming the cycle and handle the deletion manually or via trigger.
So normally that's what you should do when such cycle exists.
But here looks like something is wrong with the model. Either Patient should not be linked to a single Doctor, but to many via linking table and removing Patient.Doctor navigation property (thus the associated FK relationship), thus naturally breaking the multiple cascade paths, i.e. deleting Doctor deletes just links to clinics and patients, but not clinics and patients themselves.
Or, if you want to keep Patient to single Doctor relationship, then Consultation.Doctor (and associated Consultation.DoctorId FK and relationship) is redundant - the doctor of the consultation can be obtained via consultation.Patient.Doctor). So remove it and that will also solve the multiple cascade paths issue since there will be no more Doctor -> Consultation cascade delete link.
For clarity, the first suggested option requires the following model changes:
[Table("Clinics")]
public class Clinic // Unchanged
{
public int ClinicID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Address { get; set; }
public List<Doctor> DoctorsAvailable { get; set; } = new List<Doctor>();
}
[Table("Doctors")]
public class Doctor
{
public int ID { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public List<Clinic> ClinicsAvailableAt { get; set; } = new List<Clinic>();
public ICollection<Patient> Patients { get; set; } // <-- added
}
[Table("Patients")]
public class Patient
{
public int PatientID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
//public int DoctorID { get; set; } <-- removed
//public Doctor Doctor { get; set; } <-- removed
public ICollection<Doctor> Doctors { get; set; } // <-- added
}
[Table("Consultations")]
public class Consultation // Unchanged
{
public int ID { get; set; }
public int ClinicID { get; set; }
public int DoctorID { get; set; }
public int PatientID { get; set; }
public Clinic Clinic { get; set; }
[ForeignKey("DoctorID")]
public Doctor Doctor { get; set; }
[ForeignKey("PatientID")]
public Patient Patient { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
}
and option 2:
[Table("Clinics")]
public class Clinic // Unchanged
{
public int ClinicID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Address { get; set; }
public List<Doctor> DoctorsAvailable { get; set; } = new List<Doctor>();
}
[Table("Doctors")]
public class Doctor // Unchanged
{
public int ID { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public List<Clinic> ClinicsAvailableAt { get; set; } = new List<Clinic>();
}
[Table("Patients")]
public class Patient // Unchanged
{
public int PatientID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public int DoctorID { get; set; }
public Doctor Doctor { get; set; }
}
[Table("Consultations")]
public class Consultation
{
public int ID { get; set; }
public int ClinicID { get; set; }
//public int DoctorID { get; set; } <-- removed
public int PatientID { get; set; }
public Clinic Clinic { get; set; }
//[ForeignKey("DoctorID")]
//public Doctor Doctor { get; set; } <-- removed
[ForeignKey("PatientID")]
public Patient Patient { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
}

Introducing FOREIGN KEY constraint 'XYZ_ID' on table 'XXX' may cause cycles or multiple cascade paths in mvc core

I am getting this error in code first MVC CORE while inserting this and
I am doing Code first for very first Time
command:
Update-Database -Context ProjectDbContext
"Introducing FOREIGN KEY constraint 'FK_Product_SubCategory_SubCategoryId'
on table 'Product' may cause cycles or multiple cascade paths. Specify
ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY
constraints".
My Classes are are given below and also explain me why we use association in mvc model classes like this :
public virtual SubCategory SubCategory { get; set; }
Or
public virtual ICollection<Category> Category { get; set; }
public virtual Icollection<SubCategory> SubCategory { get; set; }
public class Product
{
public int ProductId { get; set; }
[Required]
public string ProductName { get; set; }
[Required]
public string ProductModel { get; set; }
[Required]
public int Quatity { get; set; }
[Required]
public int Price { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string ProductColor { get; set; }
public byte Status { get; set; }
public DateTime TodayDate { get; set; }
[Required]
public int CategoryId { get; set; }
[Required]
public int SubCategoryId { get; set; }
public virtual Category Category { get; set; }
public virtual SubCategory SubCategory { get; set; }
}
public class SubCategory
{
public int SubCategoryId { get; set; }
[Required]
public string SubCategoryName { set; get; }
[Required]
public int CategoryId { get; set; }
public ICollection< Category> Category { set; get; }
public ICollection<Product> Product { set; get; }
}
public class Category
{
public int CategoryId { set; get; }
[Required]
public string Name { get; set; }
}
add Following in identity model file under ApplicationDbContext class
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
hope this will help but your cascade delete will be off.

MVC Model Poco class, design issue,

i have a little issue.
I am trying to make a Address class were i save all my application's addresses.
The thing is that i want to be able to link several addresses to both customer and company.
Can someone please show me how i should design it?
I use MVC 4 with entityFramework code first.
public class Address
{
[Key]
public int AddressId { get; set; }
public string Street { get; set; }
public string Number { get; set; }
public string ZipCode { get; set; }
public int CountyId { get; set; }
public virtual County County { get; set; }
public int StateId { get; set; }
public virtual State State { get; set; }
public int CountryId { get; set; }
public virtual Country Country { get; set; }
}
public class Customer
{
[Key]
public int CustomerId { get; set; }
public int CompanyId { get; set; }
[Display(Name = "Kund")]
public string Name { get; set; }
public virtual Company Company { get; set; }
// wan't to display a ICollection of addresses.
//public virtual ICollection<Address> Addresses { get; set; }
}
public class Company
{
[Key]
public int CompanyId { get; set; }
[Display(Name = "Organisationsnummer")]
public string OrganisationNumber { get; set; }
[Display(Name = "Företag")]
public string Name { get; set; }
[Display(Name = "Företag skapat")]
public DateTime CreationDate { get; set; }
public virtual ICollection<Customer> Customers { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
// wan't to display a ICollection of addresses.
//public virtual ICollection<Address> Addresses { get; set; }
}
At the following properties and annotations to your classes, it should help Entity Framework understand your relationships:
public class Address
{
[Key]
public int AddressId { get; set; }
public string Street { get; set; }
public string Number { get; set; }
public string ZipCode { get; set; }
public int CustomerId {get;set;}
[ForeignKey("CustomerId")]
public virtual Customer Customer {get;set;}
public int CompanyId {get;set;}
[ForeignKey("CompanyId")]
public virtual Company Company {get;set;}
public int CountyId { get; set; }
[ForeignKey("CountyId")]
public virtual County County { get; set; }
public int StateId { get; set; }
[ForeignKey("StateId")]
public virtual State State { get; set; }
public int CountryId { get; set; }
[ForeignKey("CountryId")]
public virtual Country Country { get; set; }
}
public class Customer
{
[Key]
public int CustomerId { get; set; }
public int CompanyId { get; set; }
[Display(Name = "Kund")]
public string Name { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[InverseProperty("Customer")]
public virtual ICollection<Address> Addresses { get; set; }
}
public class Company
{
[Key]
public int CompanyId { get; set; }
[Display(Name = "Organisationsnummer")]
public string OrganisationNumber { get; set; }
[Display(Name = "Företag")]
public string Name { get; set; }
[Display(Name = "Företag skapat")]
public DateTime CreationDate { get; set; }
[InverseProperty("Company")]
public virtual ICollection<Customer> Customers { get; set; }
[InverseProperty("Company")]
public virtual ICollection<Address> Addresses { get; set; }
[InverseProperty("Company")]
public virtual ICollection<Employee> Employees { get; set; }
}
public class Employee
{
[Key]
public int EmployeeId {get;set;}
public int CompanyId {get;set;}
[ForeignKey("CompanyId")]
public virtual Company Company {get;set;}
}
EDIT: You now have issue of another type. Your DELETE/UPDATE rules are causing the error you're seeing right now. You've most likely set CASCADE delete on multiple paths that lead to same primary key table. For start set all your relationships that look like this:
Then assume this scenario:
You have entities A, B and C.
Entity B has FK to entity A.
Entity C has FK to entity A and entity B.
You're allowed to set cascade delete/update only on one dependency path. This means that you can only do:
Cascade delete between A and B and cascade delete between B and C.
If you however add cascade delete between A and C as well along with above, you'll get an error you have now.

Entityframework port from model first to code first

I am still on my quest to port from a Model First to Code First implementation of EntityFramework. I have made significant progress, with the help of Eranga. I have run into another snag, and I just cant explain what is hapening. I have two Entity objects Topic and Course
A Topic can have one Course that is required
A Course can have 0 or more topics
when i execute the following linq it generates wierd SQL
var topics = from o in db.Topics where o.ParentTopic == null &&
o.Course.Id == c.Id select o;
The SQL generated is
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[ShortDescription] AS [ShortDescription],
[Extent1].[LongDescription] AS [LongDescription],
[Extent1].[Property] AS [Property],
[Extent1].[Difficulty] AS [Difficulty],
[Extent1].[Weight] AS [Weight],
[Extent1].[Course_Id] AS [Course_Id],
[Extent1].[ParentTopic_Id] AS [ParentTopic_Id],
[Extent1].[Course_Id1] AS [Course_Id1]
FROM [dbo].[Topics] AS [Extent1]
WHERE ([Extent1].[ParentTopic_Id] IS NULL) AND ([Extent1].[Course_Id] = #p__linq__0)
Notice that there is an added field called Course_Id1 that is not in my object and not declared as a foreign key. I thought that in OnModelCreating() I had specified the parent child relationship correctly from both sides (I would have thought you only needed to do it from either side), but i cant get EntityFramework not to generate the extra field that obviously does not exist in the database. Remember my database was originally created using a ModelFirst approach.
Can anyone explain where the extra field is comming from????
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Topic
modelBuilder.Entity<Topic>()
.HasRequired(m => m.Course)
.WithMany(m=>m.Topics)
.HasForeignKey(m => m.Course_Id);
modelBuilder.Entity<Topic>()
.HasOptional(m => m.ParentTopic)
.WithMany(m => m.ChildTopics)
.HasForeignKey(m => m.ParentTopic_Id);
//////// lots of code removed for brevity. //////
modelBuilder.Entity<Course>()
.HasMany(m=>m.Topics)
.WithRequired(m => m.Course)
.HasForeignKey(m => m.Course_Id);
}
public partial class Topic
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
public string Property { get; set; }
public double? Difficulty { get; set; }
public double? Weight { get; set; }
[JsonIgnore]
public virtual Course Course { get; set; }
public int Course_Id { get; set; }
[JsonIgnore]
public virtual ICollection<Question> Questions { get; set; }
[JsonIgnore]
public virtual ICollection<Topic> ChildTopics { get; set; }
[JsonIgnore]
public virtual Topic ParentTopic { get; set; }
public int? ParentTopic_Id { get; set; }
[JsonIgnore]
public virtual ICollection<RTIQueueEntryData> RTIQueueEntryData { get; set; }
[JsonIgnore]
public virtual ICollection<Intervention> Interventions { get; set; }
[JsonIgnore]
public virtual ICollection<RtiStudentGroup> RtiStudentGroups { get; set; }
}
public partial class Course
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public string Version { get; set; }
public string Year { get; set; }
public string ImportedId { get; set; }
[Required]
public string LocalCourseNumber { get; set; }
[Required]
public string NCESCourseNumber { get; set; }
[Required]
public string StateCourseNumber { get; set; }
public int? Grade { get; set; }
[JsonIgnore]
public virtual ICollection<Topic> PerformanceIndicators { get; set; }
[JsonIgnore]
public virtual Department Department { get; set; }
public int DepartmentId { get; set; }
[JsonIgnore]
public virtual ICollection<StudentGroup> StudentGroups { get; set; }
[JsonIgnore]
public virtual ICollection<CutPointTemplate> CutPointTemplates { get; set; }
[JsonIgnore]
public virtual School School { get; set; }
public int School_Id { get; set; }
[JsonIgnore]
public virtual ICollection<Staff> RTIStaff { get; set; }
[JsonIgnore]
public virtual ICollection<Topic> Topics { get; set; }
}
You have another relationship between Course and Topic created by convention due to this navigation property:
public virtual ICollection<Topic> PerformanceIndicators { get; set; }
EF will put an (invisible, not exposed) end of the relationship into the Topic class. By default the relationship is one-to-many. Hence you get an additional foreign key property in the Topics table (= Course_Id1).

MVC - Entity framework - Metadata relation

Today I've been working with MVC for the first time. Also normally I use the EF with model first, but I wanted to try POCO.
So I've made my 3 entities and when I try to make a controller I get an error:
Unable to retrieve metadata for "BookExchange.Models.Exchange". Unable to determine the principal end of an association between the types "BookExchange.Models.Exchange" and "BookExchange.Models.Book". The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
My 3 classes:
public class Book
{
public int BookID { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string ISBN10 { get; set; }
public int PersonID { get; set; }
public virtual Person Person { get; set; }
public virtual Exchange Exchange { get; set; }
}
public class Person
{
public int PersonID { get; set; }
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
public virtual ICollection<Exchange> Exchanges { get; set; }
}
public class Exchange
{
[Key]
public int BookID { get; set; }
public int PersonID { get; set; }
public DateTime ReturnDate { get; set; }
public virtual Person Person { get; set; }
public virtual Book Book { get; set; }
}
Does anyone know what I'm doing wrong? I don't want to lose the association properties.
Thanks in advance!
Try adding foreign key properties for your references. E.g.
public class Book
{
public int BookID { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string ISBN10 { get; set; }
public virtual Person Person { get; set; }
public int PersonID { get; set; }
public virtual Exchange Exchange { get; set; }
public int ExchangeID { get; set; }
}
public class Person
{
public int PersonID { get; set; }
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
public virtual ICollection<Exchange> Exchanges { get; set; }
}
public class Exchange
{
public int ExchangeID { get; set; }
public int BookID { get; set; }
public virtual Book Book { get; set; }
public int PersonID { get; set; }
public virtual Person Person { get; set; }
public DateTime ReturnDate { get; set; }
}
Also, take a look at ScottGu's post on code first and this EF post on conventions.
Try this: (Remove database, so EF will create new)
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string ISBN { get; set; }
public virtual Person Person { get; set; }
public virtual Exchange Exchange { get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
public virtual ICollection<Exchange> Exchanges { get; set; }
}
public class Exchange
{
public int Id { get; set; }
public DateTime ReturnDate { get; set; }
public virtual Person Person { get; set; }
public virtual Book Book { get; set; }
}
It's your one on one associations.
Remove one reference between exchange or book, so Code-first can decide which one is more important in your one on one relation (Book <--> Exchange)
If you want to know why, you should read this:

Resources