New to EF here and having some difficulty.
I have about 24 tables I need to create with code-first. Each one of these tables has around 2 - 10 many-to-one relationships that are simple and can be represented with 1 table. Here are just a few of my classes to illustrate my structure...
namespace EMRS
{
public class ERecord
{
[Key]
public int PCRId { get; set; }
public virtual List<EFirstClass> EFirstClass {get; set;}
public virtual List<ESecondClass> ESecondClass { get; set; }
}
public class EFirstElement
{
[Key]
public int ElementId { get; set; }
public ElementCode stuff1 { get; set; } //eAirway.06
public string stuff2 { get; set; }
public int PCRId { get; set; }
public virtual ERecord EReportId { get; set; }
public virtual List<SubElement> Stuff4List { get; set; }
public virtual List<SubElement> Stuff5List { get; set; }
public virtual List<SubElement> Stuff6List { get; set; }
public virtual List<SubElement> Stuff7List { get; set; }
}
public class ESecondElement
{
[Key]
public int ElementId { get; set; }
public ElementCode Stuff9 { get; set; }
public ElementCode Stuff10 { get; set; }
public int PCRId { get; set; }
public virtual ERecord EReportId { get; set; }
public virtual List<SubElement> StuffList11 { get; set; }
public virtual List<SubElement> StuffList12 { get; set; }
public virtual List<SubElement> StuffList13 { get; set; }
public virtual List<SubElement> StuffList14 { get; set; }
public virtual List<SubElement> StuffList15 { get; set; }
public virtual List<SubElement> StuffList16 { get; set; }
public virtual List<SubElement> StuffList17 { get; set; }
}
public class SubElement
{
public int SubElementId { get; set; }
public string Value { get; set; }
public dynamic Type { get; set; }
public int ElementId { get; set; }
}
}
If I were to create a class/table for each individual 1 to many relationship in the element classes, I would end up with many tables with exactly the same structure. What I would like to do would be to have a foreign key in the SubElement class that references more than 1 class.
I tried having a parentelement abstract class and inheriting it in all of my element classes but EF created a table for that class(Parentelement) and placed all columns in all Element classes within that table.
Is there any way to do this with EF Code first?
Related
When i try to connect with my database and my class i got this error
But this error appear just for my Consoles,KeyboardMouse and Headphones tables. But they have already primary keys.
and here is my context class
public class EcommContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"Server=.;Database=eCommerce;Trusted_Connection=true");
}
public DbSet<Product> Products { get; set; }
public DbSet<Card> Cards { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Consoles> Consoles { get; set; }
public DbSet<Headphone> Headphones { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
public DbSet<Mouse> Mouses { get; set; }
public DbSet<MousePad> MousePads { get; set; }
public DbSet<Keyboard> Keyboards { get; set; }
public DbSet<KeyboardAndMouse> KeyboardMouse { get; set; }
public DbSet<Gamepad> Gamepads { get; set; }
public DbSet<Computer> Computers { get; set; }
}
And my entity classes
public class Headphone:IEntity
{
public int HeadphonesId { get; set; }
public int ProductId { get; set; }
public bool IsWireless { get; set; }
public string Type { get; set; }
public string Color { get; set; }
public bool IsGaming { get; set; }
}
public class KeyboardAndMouse:IEntity
{
public int KmId { get; set; }
public int ProductId { get; set; }
public string Color { get; set; }
}
public class Consoles:IEntity
{
public int ConsoleId { get; set; }
public int ProductId { get; set; }
public string Color { get; set; }
public int GamepadNumber { get; set; }
public int Capacity { get; set; }
}
How can I solve that. Does anyone help me ?
In your entity class you need to use [Key] annotation for primary key field. Try like below.
public class Headphone:IEntity
{
[Key]
public int HeadphonesId { get; set; }
}
public class KeyboardAndMouse:IEntity
{
[Key]
public int KmId { get; set; }
}
public class Consoles:IEntity
{
[Key]
public int ConsoleId { get; set; }
}
Please check this out for more information : https://learn.microsoft.com/en-us/ef/core/modeling/keys?tabs=data-annotations#configuring-a-primary-key
FYI - By convention, a property named Id or <type name>Id will be configured as the primary key of an entity.
So if you had HeadphoneId field in Headphone class then it will select that column as primary key by convention and no need to use [Key] annotation or Fluent API to define Primary key field.
How can I use a primary key as a foreign key of another table's in two columns.
public class ResumeSharing
{
[Key]
public int ResumeSharingId { get; set; }
[ForeignKey("AppliedJobs")]
public int AppliedJobId { get; set; }
public virtual AppliedJob AppliedJobs { get; set; }
public bool OwnCompany { get; set; }
[Display(Name = "RecruiterFrom")]
public int RecruiterId { get; set; }
public virtual Recruiter Recruiters { get; set; }
[Display(Name = "RecruiterTo")]
public int RecruiterId { get; set; }
public virtual Recruiter Recruiters { get; set; }
[ForeignKey("Companies")]
public int CompanyId { get; set; }
public virtual Company Companies { get; set; }
public string SharedFiles { get; set; }
}
I want to call RecruiterId twice in this table. How can I do this?
you have to add navigation properties
public class ResumeSharing
{
[Key]
public int ResumeSharingId { get; set; }
[ForeignKey("AppliedJob")]
public int AppliedJobId { get; set; }
public virtual AppliedJob AppliedJob { get; set; }
public bool OwnCompany { get; set; }
[Display(Name = "RecruiterFrom")]
public int RecruiterFromId { get; set; }
[ForeignKey(nameof(RecruiterFromId))]
[InverseProperty("RecruiterFroms")]
public virtual Recruiter RecruiterFrom { get; set; }
[Display(Name = "RecruiterTo")]
public int RecruiterToId { get; set; }
[ForeignKey(nameof(RecruiterToId))]
[InverseProperty("RecruiterTos")]
public virtual Recruiter RecruiterTo { get; set; }
[ForeignKey("Company")]
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
public string SharedFiles { get; set; }
}
public class Recruiter
{
[Key]
public int Id { get; set; }
[InverseProperty(nameof(ResumeSharing.RecruiterFrom))]
public virtual ICollection<Recruiter> RecruiterFroms { get; set; }
[InverseProperty(nameof(ResumeSharing.RecruiterTo))]
public virtual ICollection<Recruiter> RecruiterTos { get; set; }
}
I am running my initial EF migration trying to create the database.
But only 3 of my 5 domains are being created as tables in the database. No errors occur during migration.
I try to run SeedData methods on run, but of course it stops when it tries to save data to the table that does not exist.
I am using EF7. I use DNX to run migrations.
Does anyone know why only 3 of the tables are being created?
Here are the 2 tables that did NOT get created:
// Enumclass, this is not a table
public enum MatchTypeEnum
{
Group, RoundOf32, RoundOf16, QuarterFinals, SemiFinals, BronzeFinal, Final
}
public partial class Match
{
[Key]
public Guid MatchId { get; set; }
public DateTime KickOffTime { get; set; }
public int? HomeScore { get; set; }
public int? AwayScore { get; set; }
public Guid HomeTeamId { get; set; }
public Guid AwayTeamId { get; set; }
public MatchTypeEnum MatchType { get; set; }
public Guid? GroupId { get; set; }
public virtual Team HomeTeam { get; set; }
public virtual Team AwayTeam { get; set; }
[ForeignKey("GroupId")]
public virtual Group Group { get; set; }
}
public enum MatchOutcomeEnum
{
H,A,D
}
public partial class Bet
{
[Key]
public Guid BetId { get; set; }
public Guid UserId { get; set; }
public Guid MatchId { get; set; }
public int? HomeScore { get; set; }
public int? AwayScore { get; set; }
public MatchOutcomeEnum? MatchOutcome{ get; set; }
public int? PointsCorrectScore { get; set; }
public int? PointsBonus { get; set; }
public int? MultiplyScoreWith { get; set; }
public int? TotalPointsBet { get; set; }
[ForeignKey("MatchId")]
public virtual Match MatchBettedOn { get; set; }
}
And here are the 3 classes that do get created:
public class Team
{
[Key]
public Guid TeamId { get; set; }
public string TeamName { get; set; }
public string TeamCountry { get; set; }
public Guid GroupId { get; set; }
public string LogoUrl { get; set; }
[ForeignKey("GroupId")]
public virtual Group TeamGroup { get; set; }
}
public enum GroupEnum
{
GroupA, GroupB, GrooupC, GroupD,GroupE,GroupF, GroupG, GroupH, GroupI
}
/// <summary>
/// The group.
/// </summary>
public partial class Group
{
[Key]
public Guid GroupId { get; set; }
public GroupEnum GroupName { get; set; }
public int? NumberTeamsProceed { get; set; }
public virtual ICollection<Team> TeamsInGroup { get; set; }
public virtual ICollection<Match> MatchesInGroup { get; set; }
}
public class League
{
[Key]
public Guid LeagueId { get; set; }
public string LeagueName { get; set; }
public bool Public { get; set; }
public int LeagueNumber { get; set; }
public string LeagueLink { get; set; }
}
The DbContext:
public class CupBettingContext : DbContext
{
public CupBettingContext()
{
Database.EnsureCreated();
}
public DbSet<Group> Groups { get; set; }
public DbSet<Match> Matches { get; set; }
public DbSet<Bet> Bets { get; set; }
public DbSet<League> Leagues { get; set; }
public DbSet<Team> Teams { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connectionString = Startup.Configuration["Data:CupBettingContextConnection"];
optionsBuilder.UseSqlServer(connectionString);
base.OnConfiguring(optionsBuilder);
}
}
Thank you for your time :)
UPDATE:
It worked after I I removed the two lines from the class Match:
public virtual Team HomeTeam { get; set; }
public virtual Team AwayTeam { get; set; }
Strange that it ran the migration :/
If anyone is still reading this question, how can I add those virtual object without getting an error?
I'm new to Entity Framework and I've run into some problems while trying to implement my ERD Code First. The situation is as follows:
ERD
A product has a group of questions (QuestionGroup). A QuestionGroup has multiple questions and can belong to multiple Questionaires. A Questionaire basically has a questiongroup and a questionorder. The questionorder is supposed to keep the position of a question within that questionaire. The Questionaire table is needed because a QuestionGroup can have multiple questionorders, and a questionorder can belong to multiple questiongroups.
Because I'm trying my best to keep this post succinct I won't post all my classes, unless you ask to see them. The Entity classes I've made look like this:
public class Question
{
[Key]
public int Id { get; set; }
[MaxLength(2000)]
[Required]
public string Text { get; set; }
public Answer Answer { get; set; }
public QuestionType Type { get; set; }
public ICollection<QuestionAnswerOption> Options { get; set; }
public ICollection<QuestionOrder> Orders { get; set; }
[ForeignKey("FollowupQuestion")]
public int QuestionId { get; set; }
public virtual Question FollowupQuestion { get; set; }
[ForeignKey("Questiongroup")]
public int QuestionGroupId { get; set; }
public virtual QuestionGroup Questiongroup { get; set; }
}
public class QuestionOrder
{
[Key]
public int Id { get; set; }
public int Position { get; set; }
[ForeignKey("Question")]
[Required]
public int QuestionId { get; set; }
public virtual Question Question { get; set; }
[ForeignKey("Questionaire")]
[Required]
public int QuestionaireId { get; set; }
public virtual Questionaire Questionaire { get; set; }
}
public class Product
{
[Key]
public int Id { get; set; }
[MaxLength(150)]
[Required]
[Index(IsUnique = true)]
public string Name { get; set; }
[MaxLength(500)]
public string Summary { get; set; }
[MaxLength(500)]
public string Examples { get; set; }
public virtual QuestionGroup QuestionGroup { get; set; }
}
public class QuestionGroup
{
[Key]
public int Id { get; set; }
public ICollection<Question> Questions { get; set; }
[ForeignKey("Product")]
public int ProductId { get; set; }
public virtual Product Product { get; set; }
}
public class Questionaire
{
[Key]
public int Id { get; set; }
public QuestionGroup Group { get; set; }
public QuestionOrder Order { get; set; }
}
The errors I'm getting look like this:
QuestionGroup_Product_Source: : Multiplicity is not valid in Role 'QuestionGroup_Product_Source' in relationship 'QuestionGroup_Product'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
QuestionOrder_Questionaire_Source: : Multiplicity is not valid in Role 'QuestionOrder_Questionaire_Source' in relationship 'QuestionOrder_Questionaire'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
QuestionType_Question_Source: : Multiplicity is not valid in Role 'QuestionType_Question_Source' in relationship 'QuestionType_Question'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
The question we've arrived at here is:
Does anyone here know of a way to fix the relations between my tables? Maybe my ERD needs some improvements too, but I think the problem is that I'm missing a few things with my Code First implementation.
what about this design for you;)
public class Customer
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CustomerId { get; set; }
public string CompanyName { get; set; }
public virtual ICollection<ContactInfo> ContactInfoes { get; set; }
public virtual ICollection<ProductQuestionaireReport> Reports { get; set; }
}
public class ContactInfo
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int ContactInfoId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Telephone { get; set; }
[ForeignKey("Customer")]
public int CustomerId { get; set; }
public virtual Customer Customer { get; set; }
}
public class ProductQuestionaireReport
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductQuestionaireReportId { get; set; }
[ForeignKey("Product")]
public int ProductId { get; set; }
public virtual Product Product { get; set; }
public virtual QuestionaireResult Result { get; set; }
[ForeignKey("Customer")]
public int CustomerId { get; set; }
public virtual Customer Customer { get; set; }
public bool Haste { get; set; }
public string Status { get; set; }
public string Comment { get; set; }
}
public class QuestionaireResult
{
[Key, ForeignKey("ProductQuestionaireReport")]
public int ProductQuestionaireReportId { get; set; }
[ForeignKey("Questionaire")]
public int QuestionaireId { get; set; }
public virtual Questionaire Questionaire { get; set; }
public DateTime SurveyCreated { get; set; }
public Double Costs { get; set; }
public Double FunctionPoints { get; set; }
public virtual ProductQuestionaireReport ProductQuestionaireReport { get; set; }
public virtual ICollection<QuestionaireAnswer> Answers { get; set; }
}
public class Product
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductId { get; set; }
public string Name { get; set; }
public string Summary { get; set; }
public string Examples { get; set; }
public virtual ICollection<Questionaire> Questionaires { get; set; }
public virtual ICollection<ProductQuestionaireReport> Reports { get; set; }
}
public class QuestionaireAnswer
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int QuestionaireAnswerId { get; set; }
[ForeignKey("QuestionaireResult")]
public int QuestionaireResultId { get; set; }
public virtual QuestionaireResult QuestionaireResult { get; set; }
[ForeignKey("QuestionaireQuestion")]
public int QuestionaireId { get; set; }
public virtual QuestionaireQuestion QuestionaireQuestion { get; set; }
[ForeignKey("Answer")]
public int AnswerId { get; set; }
public virtual QuestionOption Answer { get; set; }
public string Text { get; set; }
public virtual ICollection<string> Files { get; set; }
}
public class Questionaire
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int QuestionaireId { get; set; }
[ForeignKey("Product")]
public int ProductId { get; set; }
public virtual Product Product { get; set; }
public virtual ICollection<QuestionaireQuestion> QuestionaireQuestions { get; set; }
public virtual ICollection<QuestionaireResult> Results { get; set; }
}
public class Question
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int QuestionId { get; set; }
[ForeignKey("ParentQuestion")]
public int ParentQuestionId { get; set; }
public virtual Question ParentQuestion { get; set; }
public virtual QuestionType QuestionType { get; set; }
public virtual ICollection<QuestionOption> Options { get; set; }
}
public class QuestionType
{
[Key, ForeignKey("Question")]
public int QuestionId { get; set; }
public string Text { get; set; }
public bool IsOpenQuestion { get; set; }
public virtual Question Question { get; set; }
}
public class QuestionOption
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int QuestionAnswerOptionId { get; set; }
[ForeignKey("Question")]
public int QuestionId { get; set; }
public string Text { get; set; }
public virtual Question Question { get; set; }
}
public class QuestionaireQuestion
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int QuestionaireQuestionId { get; set; }
[ForeignKey("Questionaire")]
public int QuestionaireId { get; set; }
public virtual Questionaire Questionaire { get; set; }
[ForeignKey("Question")]
public int QuestionId { get; set; }
public int DisplayOrder { get; set; }
public virtual Question Question { get; set; }
}
also you must add this to OnModelCreating
modelBuilder.Entity<Customer>().HasMany(c => c.ContactInfoes)
.WithRequired(i => i.Customer).HasForeignKey(i => i.CustomerId).WillCascadeOnDelete(false);
modelBuilder.Entity<Question>().HasMany(q => q.Options)
.WithRequired(o => o.Question).HasForeignKey(o => o.QuestionId).WillCascadeOnDelete(false);
modelBuilder.Entity<QuestionaireResult>().HasMany(r => r.Answers)
.WithRequired(a => a.QuestionaireResult).HasForeignKey(o => o.QuestionaireResultId).WillCascadeOnDelete(false);
check it and feedback me ...
I have a Template class
public class Template
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual Template RelatedTemplate { get; set; }
public virtual Field RelatedTemplatePrimaryField { get; set; }
public virtual ICollection<Field> Fields { get; set; }
}
And a Field class
public class Field
{
public int Id { get; set; }
public string Name { get; set; }
public int Min { get; set; }
public int Max { get; set; }
public bool AllowEmpty { get; set; }
public bool IsCollection { get; set; }
public virtual ICollection<Template> Templates { get; set; }
}
The problem is it's not creating a many to many relationship, it just adds a FK on the fields table, I want a many to many relationship on
Fields ICollection<Field> Fields
and
ICollection<Template> Templates
EDIT:
If I remove
public virtual Template RelatedTemplate { get; set; }
public virtual Field RelatedTemplatePrimaryField { get; set; }
It works... Any ideas?
This is a case where you must help EF to correctly recognize your relations. You can do it either by data annotations:
[InverseProperty("Fields")]
public virtual ICollection<Template> Templates { get; set; }
or by fluent-API:
modelBuilder.Entity<Template>()
.HasMany(t => t.Fields)
.WithMany(f => f.Templates);