Populating entities in Many-to-Many relationship - c#

I have an entity that has a composed primary key. I was wondering how could I populate this entity: do I need to explicitly populate the navigation properties with references or just the ID's?
I am using EF core 7
The entity is the following:
[PrimaryKey(nameof(ClassifierId), nameof(SliceId), nameof(VulnerabilityClassId), nameof(Date))]
public class Classification
{
[Column(name: "classifier_id")]
public int ClassifierId { get; set; }
public Classifier Classifier { get; set; } = null!;
[Column(name: "slice_id")]
public int SliceId { get; set; }
public Slice Slice { get; set; } = null!;
[Column(name: "vuln_class_id")]
public int VulnerabilityClassId { get; set; }
public VulnerabilityClass VulnerabilityClass { get; set; } = null!;
[Column(name: "date")]
public DateTime Date { get; set; }
public ICollection<VulnerabilityClassification> VulnerabilityClassifications { get; set; }
public SliceVulnLabel SliceVulnLabel { get; set; }
[Required]
[Column(name: "label")]
public int Label { get; set; }
[Column(name: "comment")]
public string Comment { get; set; }
[Column(name: "is_active")]
[Required]
public int IsActive { get; set; }
[Column(name: "confidence_degree")]
[Required]
public int ConfidenceDegree { get; set; }
}

Related

EF Foreign Key constraint

I'm still studying Entity Framework and tried to create a model including the foreign keys.
But when I tried to migrate the code, I got this error
Introducing FOREIGN KEY constraint 'FK_dbo.QuestionResults_dbo.QuestionsTables_QuetionsTableId' on table 'QuestionResults' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints
These are my model classes:
public class MainDetails
{
[Key]
public int Id { get; set; }
public string Language { get; set; }
[Required]
public string CustomerName { get; set; }
[Required]
public string ContactNumber { get; set; }
public string EmailAddress { get; set; }
[DisplayName("Service Type")]
[ForeignKey("QuestionsTable")]
public int ServiceTypeId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
[Required]
public string VehicleNumber { get; set; }
[Required]
public string ServiceLocation { get; set; }
public string Suggestion { get; set; }
public bool Status { get; set; } = true;
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Created Date")]
public DateTime CreatedDate { get; set; } = DateTime.Now;
public virtual QuestionResults QuestionResults { get; set; }
public virtual IList<QuestionResults> QuestionResultsMainlist { get; set; }
public virtual IList<QuestionsTable> QuestionsTables { get; set; }
}
public class QuestionsTable
{
[Key]
public int Id { get; set; }
public string ServiceType { get; set; }
public string Question { get; set; }
public virtual IList<MainDetails> MainDetailsServiceType { get; set; }
public QuestionsTable()
{
MainDetailsServiceType = new List<MainDetails>();
}
}
public class QuestionResults
{
[Key]
public int Id { get; set; }
[DisplayName("MainDetail ID")]
[ForeignKey("MainDetails")]
public int MainDetailsId { get; set; }
public virtual MainDetails MainDetails { get; set; }
[DisplayName("MainDetail ID")]
[ForeignKey("QuestionsTable")]
public int QuetionsTableId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
[Required]
public string CustoAnswer { get; set; }
}
This is the table structure I wanted to create:
To resolve this you can use the EF Model Builder
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<QuestionsTable>()
.HasRequired(a => a.MainDetails)
.WithOptionalDependent()
.WillCascadeOnDelete(false); //This is the important row
}
You'll have to play around with the type of relationship you would like along with whether you specify explicitly the foreign key. If you haven't seen this model builder before have a read here: https://learn.microsoft.com/en-us/ef/core/modeling/
Upon breaking your scenario down I noticed some "oddities". I reduced the noise in the domain model to from your example to this
public class MainDetails
{
[Key]
public int Id { get; set; }
[ForeignKey("QuestionsTable")]
public int ServiceTypeId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
public virtual QuestionResults QuestionResults { get; set; }
public virtual IList<QuestionResults> QuestionResultsMainlist { get; set; }
public virtual IList<QuestionsTable> QuestionsTables { get; set; }
}
public class QuestionsTable
{
[Key]
public int Id { get; set; }
public string ServiceType { get; set; }
public string Question { get; set; }
public virtual IList<MainDetails> MainDetailsServiceType { get; set; }
}
public class QuestionResults
{
[Key]
public int Id { get; set; }
[ForeignKey("MainDetails")]
public int MainDetailsId { get; set; }
public virtual MainDetails MainDetails { get; set; }
[ForeignKey("QuestionsTable")]
public int QuetionsTableId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
}
I few things I noted.
MainDetails contains both One-To-Many (QuestionTable) and Many-To-Many (IList) relationships? I'm unsure on your intention
QuestionsResults contains singular relationships to both entities which aren't replicated in the QuestionTable class? that's fine if it's intentional
ServiceType is a string in QuestionsTable but you are expecting an int as the foreign key in MainDetails?

How can I insert related record on the database using Code-First model

I have two tables which have one-to-many relationship between them.
public class Policy : BaseEntityAudit
{
public override string Kod { get; set; }
public PolicyType PolicyType { get; set; } = PolicyType.Policy;
public long AgentId { get; set; }
public long InsuranceTypeId { get; set; }
public string PolicyNu { get; set; }
public long OwnerId { get; set; }
public string PlateNumber { get; set; }
public string Explanation { get; set; }
public Agent Agent { get; set; }
public InsuranceType InsuranceType { get; set; }
public Owner Owner { get; set; }
public virtual ICollection<SubPolicy> SubPolicies { get; set; }
}
public class SubPolicy : BaseEntityAudit
{
public override string Kod { get; set; }
public long PolicyId { get; set; }
public DateTime IssueDate { get; set; } = DateTime.Now.Date;
public DateTime StartDate { get; set; } = DateTime.Now.Date;
public DateTime EndDate { get; set; } = DateTime.Now.AddYears(1);
public decimal Premium { get; set; }
public long InsurerId { get; set; }
[StringLength(50)]
public Policy Policy { get; set; }
public Insurer Insurer { get; set; }
}
How can I insert related records of these tables to database under one side of one-to-many relationship, so under Policy entity?
Attention:I'm using EF Code-First model, not Db-First;

There are no primary in referenced table 'x' that match referencing column foreign key ".y"

There are no primary or candidate keys in the referenced table 'dbo.Client_Master' that match the referencing column list in the foreign key 'FK_dbo.Client_Question_Master_dbo.Client_Master_client_id'.
Could not create constraint or index. See previous errors.
My Client_Master Model
public class Client_Master
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Client_Id { get; set; }
public string Client_Name { get; set; }
public string Client_Address { get; set; }
public string Client_Email { get; set; }
public string Client_Phone { get; set; }
[DefaultValue(" ")]
public string Client_Country { get; set; }
[DefaultValue(" ")]
public string Client_State { get; set; }
[DefaultValue(" ")]
public string Client_Postcode { get; set; }
public bool Is_Active { get; set; }
public long? Created_By { get; set; }
public DateTime? Created_Date { get; set; }
[ForeignKey("Business_Master")]
public long? Business_Id { get; set; }
[ForeignKey("Categories")]
public long? Category_Id { get; set; }
public virtual Categories Categories { get; set; }
public virtual Business_Master Business_Master { get; set; }
[JsonIgnore]
public virtual ICollection<Client_Question_Master> Client_Question_Master { get; set; }
}
And My Client_Question_Master Modal
public class Client_Question_Master
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long client_question_master_id { get; set; }
[ForeignKey("Client_Master")]
public long? client_id { get; set; }
public virtual Client_Master Client_Master { get; set; }
[ForeignKey("Question_Types")]
public long? question_type_id { get; set; }
public virtual Question_Types Question_Types { get; set; }
public string question { get; set; }
public long order_no { get; set; }
public bool isContribute { get; set; } = true;
[ForeignKey("Section_Master")]
public long? section_id { get; set; }
public virtual Section_Master Section_Master { get; set; }
public double amount { get; set; }
public bool isActive { get; set; } = true;
public bool isRequired { get; set; } = true;
public bool isComment { get; set; } = true;
public string values { get; set; }
public bool isRevenue { get; set; }
public bool isStaff { get; set; }
public bool isMarketing { get; set; }
public DateTime created_date { get; set; } = DateTime.Now;
}
After add-migration during updating database it is giving me error.
Your usage of the ForeignKey attribute is the wrong way round, when using a nullable foreign key.
For example you use:
[ForeignKey("Client_Master")]
public long? client_id { get; set; }
public virtual Client_Master Client_Master { get; set; }
However it should be:
public long? client_id { get; set; }
[ForeignKey("client_id")]
public virtual Client_Master Client_Master { get; set; }
You tell EntityFramework what property is the foreign key. This prevent it from creating a field that has the same datatype as the primary key.
Check your edmx file.Edmx may not have that column as Primary key in another table which you are using as foreign key.

Entity framework not creating join table

I will appreciate if somebody can tell me why entity framework is not creating join table for following model. It is creating table for type and feature but not the table that will join them.
public class DeviceType
{
[Display(Name = "ID")]
public int DeviceTypeID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public IEnumerable<DeviceFeature> DeviceFeatures { get; set; }
}
public class DeviceFeature
{
[Display(Name = "ID")]
public int DeviceFeatureID { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public IEnumerable<DeviceType> DeviceTypes { get; set; }
}
public class DeviceFeatureView
{
public virtual IEnumerable<DeviceType> DeviceTypes { get; set; }
public virtual IEnumerable<DeviceFeature> DeviceFeatures { get; set;
}
You do not need the bridge to create a many-to-many relationship. EF will figure it out. Change the type of the navigation properties from IEnumerable to ICollection like this:
public class DeviceType
{
public DeviceType()
{
this.DeviceFeatures = new HashSet<DeviceFeature>();
}
[Display(Name = "ID")]
public int DeviceTypeID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<DeviceFeature> DeviceFeatures { get; set; }
}
public class DeviceFeature
{
public DeviceFeature()
{
this.DeviceTypes = new HashSet<DeviceType>();
}
[Display(Name = "ID")]
public int DeviceFeatureID { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public ICollection<DeviceType> DeviceTypes { get; set; }
}
More about it here.

Entity Framework CodeFirst create relationship between 2 table on non primary key

Hello I am trying to add a migration and change the primary key of the table not to primary key as this has just become a requirement. Now that said it will always be unique, but needs to have a one to many relationship. with other tables and cascade on update.
I have found this but this isn't using DataAnnotations which i am, and want to contenue to do so.
Here are the 2 classes in question.
public partial class MProcurement
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public MProcurement()
{
Logs = new List<MLog>();
}
[Key]
public int Id { get; set; }
[Required]
[StringLength(8)]
[Index(IsUnique = true)]
public string ParcelId { get; set; } //current primary key that i want to change
[Required]
public DateTime PurchaseDate { get; set; }
[Required]
public string UserId { get; set; }
[Required]
[StringLength(10)]
public string ProducerCode { get; set; }
public FscCertType FscCertType { get; set; }
public int CountyId { get; set; }
[Required]
[StringLength(5)]
public string Zip { get; set; }
public Scale ProducerScale { get; set; }
public Scale Scale { get; set; }
public Terms Terms { get; set; }
public bool UseProducerScale { get; set; }
[ForeignKey(nameof(UserId))]
public virtual MUser User { get; set; }
[ForeignKey(nameof(ProducerCode))]
public virtual MProducer Producer { get; set; }
[ForeignKey(nameof(CountyId))]
public virtual MCounty County { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual List<MLog> Logs { get; set; }
}
public partial class MLog
{
public int Id { get; set; }
public int? Tag { get; set; }
[Required]
[MinLength(8), MaxLength(8)]
[Index("IX_Proc_Seq", 1, IsUnique = true)]
[ForeignKey(nameof(MProcurement.ParcelId))]//would like to add to MProcurement as ForignKey
public string ProcurementId { get; set; }
[Required]
public DateTime PurchaseDate { get; set; }
public Scale Scale { get; set; }
[Required]
[Index("IX_Proc_Seq",2,IsUnique = true)]
public int Seq { get; set; }
public bool DoubleLength { get; set; }
[Required]
[MaxLength(4)]
public string SpecieId { get; set; }
[Required]
public int CategoryId { get; set; }
[Required]
[MaxLength(1)]
public string Grade { get; set; }
[Required]
public int Length { get; set; }
[Required]
public int CutbackLength { get; set; }
[Required]
public int CutbackFeet { get; set; }
[Required]
public int Diameter { get; set; }
public int? Pounds { get; set; }
[Required]
public int Feet { get; set; }
[Required]
public decimal NetCost { get; set; }
[Required]
public decimal AdjCostPerFoot { get; set; }
[Required]
public decimal AdjustedNet { get; set; }
[Required]
public decimal ProducerPricePerFoot { get; set; }
[Required]
public decimal CostPerFoot { get; set; }
[Required]
public int ProducerFeet { get; set; }
public virtual MCategory Category { get; set; }
public virtual MSpecie Specie { get; set; }
public virtual MProcurement Procurement { get; set; }
}

Categories