Entity Framework 1:0..1 relation in mvc 5 - c#

I wanted to create a relation between two of my models to be 1:0..1 but all i got is a 1..* relation:
public class MedicalExamination
{
public int Id { get; set; }
public DateTime EntryDate { get; set; }
public DateTime ExecutionDate { get; set; }
public DateTime AcceptanceDate { get; set; }
public string Description { get; set; }
public string State { get; set; }
public string Result { get; set; }
public string Comment { get; set; }
public virtual Visit Visit { get; set; }
[Required]
public virtual ExaminationDictionary ExaminationDictionary { get; set; }
}
and my second model:
public class ExaminationDictionary
{
[Key]
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public virtual MedicalExamination MedicalExamination { get; set; }
}
And after i ran it and updated the database i got a relation like this: http://scr.hu/11m6/4eny0
The thing is that i would like it to be 0..1:1 relation. Does anybody know a good solution for this ?

A 1-to-1 or 1-to-0or1 relation in Entity Framework is only possible if both tables share the same primary key.
So for example, your MedicalExamination is presumably the principal entity in the relationship. It has an Id column primary key. Your ExaminationDictionary table needs to have an Id column that is its primary.
You then describe the relationship using Fluent API like so:
modelBuilder.Entity<MedicalExamination>()
.HasOptional(m=>m.ExaminationDictionary)
.WithRequiredPrincipal(d=>d.MedicalExamination);

Related

Entity Framework C# Introducing A Foreign Key X In Table Y May Cause Cycles OR Multiple Cascade Paths

I am developing a C# MVC application. I am using Code First approach to model my database.
My project had the following requirements:
Company Can Have Many Products
Product Can have many Advertisement
Types
Here are model classes (code first solution) to the above mentioned problem.
public class Company
{
public Company()
{
this.Employees = new HashSet<ApplicationUser>();
}
public int ID { get; set; }
[Required]
public string Name { get; set; }
public string Logo { get; set; }
[Display(Name="Company Description")]
public string CompanyDescription { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
public virtual ICollection<ApplicationUser> Employees { get; set; }
public virtual ICollection<Client> Clients { get; set; }
public ICollection<Product> Products { get; set; }
}
public class Product
{
public int ProductID { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
public string ProductName { get; set; }
public int CompanyID { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<AdvertisementType> AdvertisementTypes { get; set; }
}
public class AdvertisementType
{
public int AdvertisementTypeID { get; set; }
public int ProductID { get; set; }
[Display(Name = "Advertisement Name")]
public string AdvertisementTypeName { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
public virtual Product Product { get; set; }
}
When I try to update the database, after creating the migrations i get the following error:
Introducing FOREIGN KEY constraint 'FK_dbo.AdvertisementTypes_dbo.Products_ProductID' on table 'AdvertisementTypes' 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.
I have been trying solve this problem but unable to find any solution. I don't find any problem with the model classes, nor i think there are any issues with the relationship between the models.
Any suggestions or help will be useful.
EDIT
Here is screenshot of Tables and their relations
in your dbContext you need to turn cascade delete to false if you want to avoid that.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
You can initialize your make a List() in Product like you did with Company class...
public class Product
{
public int ProductID { get; set; }
public Product()
{
this.AdvertisementTypes = new List<AdvertisementType>();
}

Invalid column name TableName_ID error

I have two tables
PropertyListing - It stores the details of the property user add, with an FK
PropertyAvailability - It's a table that stores property status ( Now Available, After 3 Months, ...)
I am trying to enforce a one-to-many relation with these two tables (Fluent API) like this
public partial class PropertyListing
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string StreetAddress { get; set; }
//the column that links with PropertyAvaibility table PK
public byte? Availability { get; set; }
public bool Status { get; set; }
public virtual PropertyAvailability PropertyAvailability { get; set; }
}
public partial class PropertyAvailability
{
public byte ID { get; set; }
public string Status { get; set; }
public virtual ICollection<PropertyListing> PropertyListings { get; set; }
public PropertyAvailability()
{
PropertyListings = new List<PropertyListing>();
}
}
I am calling this on OnModelCreating
modelBuilder.Entity<PropertyListing>()
.HasRequired(pl => pl.PropertyAvailability)
.WithMany(pa => pa.PropertyListings)
.HasForeignKey(pl => pl.Availability);
It fails with this error,
Invalid column name 'PropertyListing_ID'.
Tutorial I used: http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx
What could be wrong? I know I have screwed up the naming convention EF6 expects, but isn't there a workaround?
P.S: I have seen this question asked from ef3 or so in our SO, but I am unable to find any solution and hence the question.
Add the Column attribute to you class
public partial class PropertyListing
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), Column("ID")]
public int ID { get; set; }
public string StreetAddress { get; set; }
//the column that links with PropertyAvaibility table PK
public byte? Availability { get; set; }
public bool Status { get; set; }
public virtual PropertyAvailability PropertyAvailability { get; set; }
}

Create one to one relation using code first approch in entitiy framework

I have below two classes and i wanted to make a one to one relation between these two entities using Code First approch. Anybody can suggest/help me on how to create ONE to ONE relation between these Patient & Address entities ? Thanks in advance...
public partial class Patient
{
public Patient()
{
this.Clinicals = new List<Clinical>();
}
public int PatientId { get; set; }
public string MaritalStatus { get; set; }
public Nullable<System.DateTime> ModifiedDate { get; set; }
public virtual ICollection<Clinical> Clinicals { get; set; }
[Required]
public virtual Address Address { get; set; }
}
public partial class Address
{
public int AddressId { get; set; }
[ForeignKey("Patient")]
public int PatientId { get; set; }
public string AddressLine1 { get; set; }
public string State { get; set; }
public Nullable<System.DateTime> ModifiedDate { get; set; }
public virtual Patient Patient { get; set; }
}
If you run your application Entity Framework will create one-to-one relationship automatically for you.Because you have added necessary properties for this. Anyway, if you want to create it manually you can use Fluent API:
modelBuilder.Entity<Patient>()
.HasRequired(a => a.Address)
.WithRequiredPrincipal(p => p.Patient);

Only mapping to subset of a table

Weird question here.
I have a bad situation with a database I can't change.
[Table("PROJTABLE")]
public class Certifikat {
[Key]
public long Recid { get; set; }
public String DATAAREAID { get; set; }
public String Projid { get; set; }
public virtual StandardAndScope StandardInfo { get; set; }
}
[Table("DS_CRT_PROJSTANDARDSCOPE")]
public class StandardAndScope {
[Key]
public long RECID { get; set; }
public String DATAAREAID { get; set; }
public String Standard { get; set; }
public String Scope { get; set; }
}
I have an optional one-to-many relationship from Certifikat to StandardAndScope. However! It's only one-to-many if the DATAAREAID column is a certain value ("crt").
Do I have any way of telling EntityFramework only to map rows where the value of that column is crt?

Entity Framework 5 Code First Relationships

I'm having trouble understanding how to create relationships between classes on a project that I'm building.
I have a class Photo that has a required one-to-one relationship with PhotoExif, and Photo has an optional one-to-one relationship with FeaturedPhoto.
I'm getting the error:
Unable to determine composite primary key ordering for type Website.Models.PhotoExif. Use the ColumnAttribute or the HasKey method to specify an order for composite primary keys.
Help would be much appreciated.
Photo.cs
public class Photo
{
[Key]
public int PhotoID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public Orientation Orientation { get; set; }
public int Rating { get; set; }
public string URL { get; set; }
public string Filename { get; set; }
public DateTime DateAdded { get; set; }
public bool Hide { get; set; }
public string MetaDescription { get; set; }
public string MetaKeywords { get; set; }
public virtual PhotoExif PhotoExif { get; set; }
}
PhotoExif.cs
public class PhotoExif
{
[Key]
public int PhotoExifID { get; set; }
public int PhotoID { get; set; }
public string ShutterSpeed { get; set; }
public string Aperture { get; set; }
public string FocalLength { get; set; }
public int ISO { get; set; }
public string ExposureBias { get; set; }
public bool Flash { get; set; }
public string WhiteBalance { get; set; }
public string Lens { get; set; }
public DateTime DateTaken { get; set; }
public float Longitude { get; set; }
public float Latitude { get; set; }
public int Zoom { get; set; }
public string Location { get; set; }
public virtual Photo Photo { get; set; }
}
FeaturedPhoto.cs
public class FeaturedPhoto
{
[Key]
public int FeaturedPhotoID { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string InformationLocation { get; set; }
public string ImagePosition { get; set; }
public virtual Photo Photo { get; set; }
}
As per the error message:
Use the ColumnAttribute or the HasKey method to specify an order for
composite primary keys.
you need to add [Column(Order="#")] annotations to PhotoID and PhotoExifID properties of the PhotoExif table.
To me it looks that you don't want a composite primary key on PhotoExif. I don't know why EF tries to infer a composite key, but the reason is possibly 1) that the Photo property has the PhotoID property as foreign key by convention, 2) in a one-to-one relationship the foreign key must be identical with the primary key, 3) there is another property PhotoExifID you have marked a key. So, maybe, EF assumes that this marked key plus the infered key from the one-to-one relationship form a composite key together. (This behaviour would be pretty strange, but I can't see how your model and your annotations could lead to this exception about composite key ordering.)
Anyway, the PhotoID property doesn't seem right, because in a one-to-one relationship principal and dependent must share the same primary key and the FK of the dependent is the PK at the same time. I would try to remove this property and add a FK attribute:
public class PhotoExif
{
[Key]
public int PhotoExifID { get; set; }
public string ShutterSpeed { get; set; }
//...
[ForeignKey("PhotoExifID")]
public virtual Photo Photo { get; set; }
}
Similarly you must define the FK for FeaturedPhoto, otherwise EF cannot determine what's the principal and what's the dependent of the relationship. Depending on the details of the relationships - are they required-required, required-optional or optional-optional and which entity is principal and which one is dependent? - it might be necessary to define the mapping with Fluent API since data annotations do not support every mapping option that Fluent API does.

Categories

Resources