EF code first specify relationship table for a navigation property - entity-framework

I am new to EF code first and am trying to force an ICollection navigation property to use a specific relationship table I've manually created for mapping the entities.
The reason I am forced to do it is that I have a TenantId column on all my tables. Is this somehow possible?
[Table("Tenants")]
public class Tenant
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// This should use ContactAddressesForTenants table
public virtual ICollection<Address> ContactAddresses {get; set;}
}
[Table("BusinessProfiles")]
public class BusinessProfile
{
[Key, ForeignKey("Tenant")]
public int TenantId { get; set; }
public virtual Tenant Tenant { get; set; }
// This should use the AddressesForBusinessProfiles table
public virtual ICollection<Address> ProfileAddresses { get; set; }
}
[Table("Addresses")]
public class Address
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("Tenant")]
public int TenantId { get; set; }
}
[Table("ContactAddressesForTenants")]
public class ContactAddressForTenant
{
[ForeignKey("Tenant")]
public int TenantId { get; set; }
[ForeignKey("Address")]
public int AddressId { get; set; }
public virtual Tenant Tenant { get; set; }
public virtual Address Address {get; set;}
}
[Table("AddressesForBusinessProfiles")]
public class AddressForBusinessProfile
{
[ForeignKey("BusinessProfile")]
public int TenantId { get; set; }
[ForeignKey("Address")]
public int AddressId { get; set; }
public virtual BusinessProfile BusinessProfile { get; set; }
public virtual Address Address { get; set; }
}

If I am understanding you correctly.
You can try changing this in your model.
Where it is:
// This should use ContactAddressesForTenants table
public virtual ICollection<Address> ContactAddresses {get; set;}
// This should use the AddressesForBusinessProfiles table
public virtual ICollection<Address> ProfileAddresses { get; set; }
Change to:
public virtual ICollection<ContactAddressForTenant> ContactAddresses {get; set;}
public virtual ICollection<AddressForBusinessProfile> ProfileAddresses { get; set; }

Related

ForeignKey with a list of ApplicationUser objects

When it comes to a single object's foreign key, we would have a property:
SingleMap.cs
[ForeignKey("ApplicationUser")]
public int ApplicationUserID { get; set; }
public ApplicationUser ApplicationUser { get; set; }
How do we map the foreignkey when we have a list of ApplicationUsers?
ManyMap.cs
public ICollection<ApplicationUser> ApplicationUserList { get; set; }
it is usually used this way:
public class ManyMap
{
public int ID {get; set;}
.....
[InverseProperty(nameof(ApplicatonUser.ManyMap))]
public ICollection<ApplicationUser> ApplicationUsers{ get; set; }
}
public class ApplicationUser
{
......
public int ManyMapID { get; set; }
[ForeignKey(nameof(ManyMapID))]
[InverseProperty("ApplicationUsers")]
public ManyMap ManyMap { get; set; }
}

EF 6 Mapping Complex Composite Keys

I have the following models
public class Company
{
[Key, Column(Order=0)]
public int Id {get;set;}
public string CompanyCode { get; set; }
public string Name { get; set; }
public virtual ICollection<Account> Accounts { get; set; }
public virtual ICollection<Journal> Journals { get; set; }
}
public class Account
{
[Key, Column(Order=0)]
public int Id { get; set; }
[Key, Column(Order=1), ForeignKey("Company")]
public int CompanyId { get; set; }
public int GLAccountNumber { get; set; }
public decimal Balance { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<Journal> Journals { get; set; }
}
public class Journal
{
[Key, Column(Order=0)]
public int Id { get; set; }
[Key, Column(Order=1), ForeignKey("Company")]
public int CompanyId { get; set; }
[ForeignKey("Account")]
public int AccountId { get; set; }
public DateTime EntryDate { get; set; }
public decimal Amount { get; set; }
public virtual Company Company { get; set; }
public virtual Account Account { get; set; }
}
How would I map the relationship between these models, Specifically I cannot figure out how to define the Composite Key in the Journal Model to map to Account By CompanyId, AccountId
You could use fluent APi (my personal preference - clear and less error prone):
modelBuilder.Entity<Journal>()
.HasRequired(e => e.Account)
.WithMany(e => e.Journals)
.HasForeignKey(e => new { e.AccountId, e.CompanyId });
But if you prefer data annotations, then apply the ForeignKey attribute on the navigation property and specify comma separated list of the FK properties:
public class Journal
{
[Key, Column(Order=0)]
public int Id { get; set; }
[Key, Column(Order=1)]
public int CompanyId { get; set; }
public int AccountId { get; set; }
public DateTime EntryDate { get; set; }
public decimal Amount { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[ForeignKey("AccountId,CompanyId")]
public virtual Account Account { get; set; }
}

One to One with attributes EF codefirst

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; }

Multiplicity not allowed. Entity Framework

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)

EF 5RC Table splitting into more than two entities

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