Can someone provide an example or explain how can I split a table into more than two entities using data annotations on EF 5 RC Code First?
I have 4 entities I want to be mapped into just one table. The code for each one of them are:
[Table("PatientDataEntities")]
public class PatientDataEntity
{
[Key]
[ForeignKey("UserFullName")]
public virtual Guid Id { get; set; }
public virtual UserFullNameEntity UserFullName { get; set; }
public virtual GeneralData GenData {get; set;}
[ForeignKey("Id")]
public virtual PersonalPatientDataEntity PersonalData { get; set; }
[ForeignKey("Id")]
public virtual MedicalPatientDataEntity MedicalData { get; set; }
[ForeignKey("Id")]
public virtual FinancialPatientDataEntity FinancialData { get; set; }
}
[Table("PatientDataEntities")]
public class PersonalPatientDataEntity
{
[Key]
[ForeignKey("UserFullName")]
public virtual Guid Id { get; set; }
public virtual UserFullNameEntity UserFullName { get; set; }
[ForeignKey("Id")]
public virtual MedicalPatientDataEntity MedicalPatientData { get; set; }
[ForeignKey("Id")]
public virtual FinancialPatientDataEntity FinancialPatientData { get; set; }
[ForeignKey("Id")]
public virtual PatientDataEntity PatientData { get; set; }
[DataType(DataType.DateTime)]
public virtual DateTime Birthdate { get; set; }
public virtual Gender Sex { get; set; }
public virtual MaritalStatus MStatus { get; set; }
public virtual byte Children { get; set; }
public virtual string Education { get; set; }
public string Profession { get; set; }
}
[Table("PatientDataEntities")]
public class MedicalPatientDataEntity
{
[Key]
[ForeignKey("UserFullName")]
public virtual Guid Id { get; set; }
public virtual UserFullNameEntity UserFullName { get; set; }
[ForeignKey("Id")]
public virtual PersonalPatientDataEntity PersonalData { get; set; }
[ForeignKey("Id")]
public virtual FinancialPatientDataEntity FinancialData { get; set; }
[ForeignKey("Id")]
public virtual PatientDataEntity PatientData { get; set; }
public virtual string ClinicalHistoryNumber { get; set; }
public virtual BiologicalState State { get; set; }
public virtual Guid PhysicianId { get; set; }
public virtual DateTime? RegisterDate { get; set; }
public virtual bool AcceptsDataTreatment { get; set; }
public virtual bool AcceptsImageTreatment { get; set; }
public virtual /*List<Allergy>*/ string Allergies { get; set; }
public virtual /*List<Surgery>*/ string Surgeries { get; set; }
public virtual /*List<Medication>*/ string Medications { get; set; }
public virtual /*List<MedicalPrecedent>*/ string MedicalPrecedents { get; set; }
[DataType(DataType.MultilineText)]
public virtual string Family { get; set; }
public virtual string Nicotinism { get; set; }
public virtual float? Weight { get; set; }
public virtual float? Height { get; set; }
[NotMapped]
public virtual float? BodyMassIndex { get; set; }
public virtual string Remarks { get; set; }
}
[Table("PatientDataEntities")]
public class FinancialPatientDataEntity
{
[Key]
[ForeignKey("UserFullName")]
public virtual Guid Id { get; set; }
public virtual UserFullNameEntity UserFullName { get; set; }
[ForeignKey("Id")]
public virtual PersonalPatientDataEntity PersonalData { get; set; }
[ForeignKey("Id")]
public virtual MedicalPatientDataEntity MedicalData { get; set; }
[ForeignKey("Id")]
public virtual PatientDataEntity PatientData { get; set; }
public virtual string KindOfPatient { get; set; }
public virtual string Isapre { get; set; }
}
And my context is this:
public class MedicDbContext : DbContext
{
public DbSet<UserFullNameEntity> UsersFullName { get; set; }
public DbSet<MedicDb.Patient.PatientDataEntity> PatientDataEntities { get; set; }
public DbSet<MedicDb.Patient.Personal.PersonalPatientDataEntity> PersonalPatientDataEntities { get; set; }
public DbSet<MedicDb.Patient.Financial.FinancialPatientDataEntity> FinancialPatientDataEntities { get; set; }
public DbSet<MedicDb.Patient.Medical.MedicalPatientDataEntity> MedicalPatientDataEntities { get; set; }
}
When I run that I receive the following exception:
An exception of type 'System.InvalidOperationException' occurred in
EntityFramework.DLL but was not handled in user code
Additional information: Unable to determine the principal end of an
association between the types
'MedicDb.Patient.Medical.MedicalPatientDataEntity' and
'MedicDb.Patient.Personal.PersonalPatientDataEntity'. The principal
end of this association must be explicitly configured using either the
relationship fluent API or data annotations.
What am I doing wrong here? I really need some help here.
Well, I fixed the problem, I guess the main cause is my ignorance on the topic, the [ForeignKey] attribute must be at just one end of the relation, that fix the exception but to make the 4 entities be on the same table there must be a one to one relation between the 4 of them, it looks a bit unnatural but that's the only way it works. So, at the end I'm not splitting my table but, instead, creating 4 separated tables having one to one relation not among the 4 of them but between the PatientDataEntity and each one of the other 3, that is done by removing the [ForeingKey] annotation from the properties in PatientDataEntity but leaving them on the other 3 entities (on the navigation properties toward PatientDataEntity.
That´s all.
That in case orther people arrives at the same problem.
Thanks to all
Juan Carlos Galvez
Related
I use EF's code first approach. I have the following three classes:
public class Inquiry
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public virtual ApplicationUser CreatedBy { get; set; }
public virtual Contractor Contractor { get; set; }
public IList<ApplicationUser> InquiryUsers { get; set; }
public IList<InquiryComment> Comments { get; set; }
public IList<HydroTechEmail> Emails { get; set; }
public InquiryState State { get; set; }
public List<string> Attachments { get; set; }
public DateTime? TimeOfCreation { get; set; }
public DateTime? TimeOfModification { get; set; }
}
public class HydroTechEmail
{
public Guid Id { get; set; }
public string Subject { get; set; }
public string Content { get; set; }
public string FromDisplayName { get; set; }
public string FromAddress { get; set; }
public List<string> ToDisplayName { get; set; }
public List<string> ToAddress { get; set; }
public HydroTechEmailState State { get; set; }
public DateTime? ReceivedTime { get; set; }
public virtual List<HydroTechEmailAttachment> Attachments { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
public class ApplicationUser
{
public Guid Id {get;set;}
public string Firstname {get;set;}
public string Lastname {get;set;}
}
I thought EF will generate some intermediate classes for relation Inquiry -> Many Emails and Inquiry -> Many Application Users. Instead it created a foreign keys in ApplicationUser and HydroTechEmail classes to Inquiry class. How should I create this one to many relations?
The strange is that for Comments it created an intermediate table named InquiryComments.
Entity Framework will only generate intermediate tables for many-to-many relationships.
For one-to-many relationships, no intermediate tables will be created because it is not necessary.
Entity Framework 6 Code First Migrations with Multiple Data Contexts
NOTE: This is my first post on Stack Overflow so please let me know if I need to provide more detail.
FYI: I have read the article:
Entity Framework 6 Code First Migrations with Multiple Data Contexts
And I'm trying to do something similar. My question/problem revolves around the CreateTable methods generated in the Configuration.cs file.
I have 29 model classes, and I'm trying to set up 4 different Data Contexts.
In my first Data Context, RulingRequestContext, I have 11 of my 29 model classes:
public class RulingRequestContext : BaseContext<RulingRequestContext>
{
public DbSet<RulingRequest> RulingRequests { get; set; }
public DbSet<Agency> Agencies { get; set; }
public DbSet<RulingRequestGroup> RulingRequestGroups { get; set; }
public DbSet<RulingRequestOverallOutcome> RulingRequestOverallOutcomes { get; set; }
public DbSet<RulingRequestType> RulingRequestTypes { get; set; }
public DbSet<RulingRequestResult> RulingRequestResults { get; set; }
public DbSet<Issue> Issues { get; set; }
public DbSet<Decision> Decisions { get; set; }
public DbSet<RulingRequestRoutingInformation> RulingRequestRoutingInformations { get; set; }
public DbSet<Staff> Staffs { get; set; }
public DbSet<StatusOfRulingRequest> StatusOfRulingRequests { get; set; }
Using Package Manager, here are 3 steps I'm following:
NOTE: These are the generic instructions:
(1) enable-migrations -ContextTypeName <DbContext-Name-with-Namespaces> -MigrationsDirectory:<Migrations-Directory-Name>
(2) Add-Migration -configuration <DbContext-Migrations-Configuration-Class-with-Namespaces> <Migrations-Name>
(3) Update-Database -configuration <DbContext-Migrations-Configuration-Class-with-Namespaces> -Verbose
Step 2 is where I have my question. After I run Step 2, I get: a folder, called RulingRequestContextMigrations with 2 files:
201502212023508_Initial.cs and Configuration.cs.
When I look at Configuration.cs. file, the function, public override void Up(), has a CreateTable function for all 29 of my model classes.
I thought that only the 11 listed in my RulingRequestContext class would be created.
Here is a snapshot of my RulingRequest model class.
public class RulingRequest
{
public RulingRequest()
{
this.RulingRequestResults = new HashSet<RulingRequestResult>();
this.RulingRequestRoutingInformations = new HashSet<RulingRequestRoutingInformation>();
}
[DisplayName("Ruling Request ID")]
public int RulingRequestID { get; set; }
[DisplayName("Employee ID Number")]
public string EmployeeIDNumber { get; set; }
[DisplayName("Case Group")]
public string RulingRequestGroupID { get; set; }
[DisplayName("Type")]
public Nullable<int> RulingRequestTypeID { get; set; }
[DisplayName("First Name")]
public string FirstName { get; set; }
[DisplayName("Last Name")]
public string LastName { get; set; }
public string MI { get; set; }
public string Suffix { get; set; }
public string Address { get; set; }
[DisplayName("Address 2")]
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public Nullable<int> Zip { get; set; }
[DisplayName("Home Phone")]
public string HomePhone { get; set; }
[DisplayName("Work Phone")]
public string WorkPhone { get; set; }
public string Email { get; set; }
[DisplayName("Agency")]
public string AgencyNumber { get; set; }
[DisplayName("Date Received")]
public Nullable<System.DateTime> DateReceived { get; set; }
[DisplayName("Grievance Initiation Date")]
public Nullable<System.DateTime> GrievanceInitiationDate { get; set; }
[DisplayName("Decision Date")]
public Nullable<System.DateTime> DecisionDate { get; set; }
[DisplayName("Re-Activation Date")]
public Nullable<System.DateTime> ReActivationDate { get; set; }
[DisplayName("Overall Outcome")]
public Nullable<int> RulingRequestOverallOutcomeID { get; set; }
[ScaffoldColumn(false)]
public string CreatedBy { get; set; }
[ScaffoldColumn(false)]
public Nullable<System.DateTime> CreatedDatetime { get; set; }
[ScaffoldColumn(false)]
public string UpdatedBy { get; set; }
[ScaffoldColumn(false)]
public Nullable<System.DateTime> UpdatedDatetime { get; set; }
public virtual Agency Agency { get; set; }
public virtual RulingRequestGroup RulingRequestGroup { get; set; }
public virtual RulingRequestOverallOutcome RulingRequestOverallOutcome { get; set; }
public virtual RulingRequestType RulingRequestType { get; set; }
public virtual ICollection<RulingRequestResult> RulingRequestResults { get; set; }
public virtual ICollection<RulingRequestRoutingInformation> RulingRequestRoutingInformations { get; set; }
}
All 4 of my Data Context classes have a model class that uses Agency and has:
public virtual Agency Agency { get; set; }
QUESTIONS:
(1) Are all 29 of my model classes being added to the RulingRequest's Configuration.cs because of the relationships/virtual properties? For example since all 4 of my Data Context classes have: public virtual Agency Agency { get; set; } all of those model classes are being added to the Configuration.cs file for my RulingRequestContext.cs class.
(2) Assuming my initial Data Context class (RulingRequestContext) and it's Configuration.cs class are working as they are supposed to, should I comment out all of the CreateTable code in the 3 other Configuration.cs classes?
(3) Or should I comment out the CreateTable code for all of the model classes that don't appear as DBSet properties in my RulingRequestContext? And then do the same for my 3 other DataContext classes?
Thanks for your time reading this! Please let me know if there's anything I can do or not do to make my posts better in the future!
Yes, it is grabbing the related entities. Your link talks about commenting out the tables from the other contexts "Before running update command, commented out the generated code for Users tables as shown above. Since Users table is already created by first DbContext migrations."
I am stuck on figuring this out. MVC 5, EntityFramework
My project revolves around a Job. Every Job has multiple ChangeOrders. I have that setup fine. A Job has one Customer. That works fine as well. my problem is with the Customer Employees. The Customer class has a one-to-many relationship with the CustomerEmployee class. Every Customer Employee has a basic properties plus a Role property. Super,PM,Accountant, or Admin. Well when I create a job, I need to select a CustomerEmployee Admin/PM etc...
What relationship would this be? A many-to-many relationship? In my mind, the Job class would need to have a CustomerEmployeeSuperId, CustomerEmployeePMId, CustomerEmployeeAdminId and CustomerEmployeeAccountantId.
Because right now all it has is CustomerEmployeeId
How do I do this?
Current Setup
public class Job
{
//job
public int JobId { get; set; }
public int? JobNumber { get; set; }
public string JobName { get; set; }
public string JobDescription { get; set; }
public int? GeoAreaId { get; set; }
public virtual JobMisc.GeoArea GeoArea { get; set; }
public int? JobClassId { get; set; }
public virtual JobMisc.JobClass JobClass { get; set; }
public int? JobTypeId { get; set; }
public virtual JobMisc.JobType JobType { get; set; }
public Int64? CustomerId { get; set; }
public virtual Customer Customer { get; set; }
public virtual ICollection<ChangeOrder> ChangeOrders { get; set; }
public virtual ICollection<PurchaseOrder> PurchaseOrders { get; set; }
public int? CustomerEmployeeId { get; set; }
public virtual ICollection<CustomerEmployee> CustomerEmployees { get; set; }
}
public class Customer
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]
public Int64 CustomerId { get; set; }
public string CustomerName { get; set; }
public Int64? CustomerPhoneNumber { get; set; }
public Int64? CustomerFaxNumber { get; set; }
public string CustomerAddress { get; set; }
public string CustomerCity { get; set; }
public string CustomerState { get; set; }
public int? CustomerZipcode { get; set; }
public string CustomerWebsite { get; set; }
public string CustomerOtherShit { get; set; }
public bool? CustomerIsHidden { get; set; }
public virtual ICollection<CustomerEmployee> CustomerEmployees { get; set; }
public List<Job> Jobs { get; set; }
}
public class CustomerEmployee
{
[Key]
public int CustomerEmployeeId { get; set; }
public string CustomerEmployeeFirstName { get; set; }
public string CustomerEmployeeLastName { get; set; }
public string CustomerEmployeeEmail { get; set; }
public Int64? CustomerEmployeePhoneNumber { get; set; }
public Int64? CustomerEmployeeCellNumber { get; set; }
public Int64? CustomerEmployeeFaxNumber { get; set; }
public bool? CustomerEmployeeIsHidden { get; set; }
public string CustomerEmployeeRole { get; set; }
public Int64? CustomerId { get; set; }
public virtual Customer Customer { get; set; }
public int? JobId { get; set; }
public virtual ICollection<Job> Jobs { get; set; }
}
Well, for the individual job, it would be a one to many relationship. For multiple jobs, it could be many to many.
Is it possible that an employee who is an Admin might also be pressed into service as a tester for certain jobs?
I'd recommend created a child table for JobRoles, one that links to the JobID, a CustomerEmployeeID, and a JobRoleID (assuming the possibility of the JobRoles being flexible).
Hope this helps...
I am trying to link two models with One to One relationship
the classes are following:
public class Customer : BaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[ForeignKey("Account")]
public int AccountId { get; set; }
public virtual Account Account { get; set; }
[Required(AllowEmptyStrings = false)]
public string Address { get; set; }
[Required(AllowEmptyStrings = false)]
public string PublicName { get; set; }
[Required]
public int UserId { get; set; }
[ForeignKey("Id")]
[InverseProperty("Customer")]
public virtual User User { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
public class User : BaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(32)]
[RegularExpression(#"^[\w]+(\.?[\w\d_]+)?$")]
public string Login { get; set; }
[Required]
[MinLength(6)]
[DataType(DataType.Password)]
[RegularExpression(#"^[\w]+(\.?[\w\d_]+)?$")]
public string Password { get; set; }
[Required]
[StringLength(32)]
[DataType(DataType.EmailAddress)]
[RegularExpression(#"^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$")]
public string Email { get; set; }
[Required]
public string Firstname { get; set; }
[Required]
public string Lastname { get; set; }
[MaxLength(256)]
public string ProfilePhoto { get; set; }
[Required]
[ForeignKey("Account")]
public int AccountId { get; set; }
[Required]
public virtual Account Account { get; set; }
[InverseProperty("User")]
public virtual ICollection<Rate> Rates { get; set; }
public int CustomerId { get; set; }
[ForeignKey("Id")]
[InverseProperty("User")]
public virtual Customer Customer { get; set; }
}
i searched did not but found solution for doing than ONLY with attributes. can anybody help me with that?
Thanks in advance!
The mistake that you're making is that you have both tables pointing to each other as having a foreign key relationship with the other. You have to pick one table as the base table and the other as being the one that has the FK in it. If you want the User table to be the base then you would do the following:
On the User class: Remove the [ForeignKey] and [InverseProperty] attributes from Customer.
On the Customer class:
[Key, ForeignKey("User")]
public int Id { get; set; }
//Other fields
public virtual User User { get; set; }
I am attempting to use MVC4 for the first time and am receiving the following error when I try to create a controller? Could someone kindly steer me in the right direction?
Microsoft Visual Studio
System.Data.Entity.Edm.EdmAssociationEnd: : Multiplicity is not valid
in Role 'PropertyData_DNISData_Target' in relationship
'PropertyData_DNISData'. Because the Dependent Role properties are not
the key properties, the upper bound of the multiplicity of the
Dependent Role must be '*'.
public class PropertyData
{
[Key]
public virtual string PropertyID { get; set; }
[ForeignKey ("DNISData")]
public virtual string DNIS { get; set; }
public virtual string PropertyName { get; set; }
public virtual string PropertyGreeting { get; set; }
public virtual string PropertyOperator { get; set; }
public virtual string InvalidEntryPrompt { get; set; }
public virtual string NoEntryPrompt { get; set; }
public virtual string Comment { get; set; }
public virtual DNISData DNISData { get; set; }
}
public class DNISData
{
[Key]
public virtual string DNIS { get; set; }
[ForeignKey("PropertyData")]
public string PropertyID { get; set; }
public virtual string VDN { get; set; }
public virtual string PropertyGreeting { get; set; }
public virtual string Comment { get; set; }
public virtual PropertyData PropertyData { get; set; }
}
public class DigitData
{
[ForeignKey ("DNISData")]
[Key]
public virtual string DNIS { get; set; }
[Key]
public virtual string Digit { get; set; }
public virtual string InvalidEntryPrompt { get; set; }
public virtual DNISData DNISData { get; set; }
}
You have a 1 to 1 relationship between PropertyData and DNISData. This can only be done via shared primarykey in EntityFramework.
This question can give you the anwser you are looking for:
How to declare one to one relationship using Entity Framework 4 Code First (POCO)