I'd like Db use Code-First
What I did:
public class Responses
{
public int UserId { get; set; }
public virtual AppUser AppUser { get; set; }
public int QuestionId { get; set; }
public virtual Question Question { get; set; }
public string Answer { get; set; }
}
public class Question
{
public int idQuestion { get; set; }
public string TextQuestion { get; set; }
public ICollection<Responses> Responses { get; set; }
}
public class AppUser : IdentityUser<int, AppUserLogin, AppUserRole, IdentityUserClaimBase>, ICRMRepository, IEditableEntity, IEntityBase
{
public int idUser {get;set;}
public ICollection<Responses> Responses { get; set; }
}
next to I go to DbContext:
modelBuilder.Entity<Responses>()
.HasKey(x => new {x.UserId, x.QuestionId});
modelBuilder.Entity<Responses>()
.HasOne(x=>x.User)
Cannot resolve symbol "HasOne"
what should I do if I would like get db like this?
How do I configure my association with fluent API? Or is there a better way to create the association table?
UPD
Change Responses class, replace AppUser property by User
public class Responses
{
public int UserId { get; set; }
public virtual AppUser User{ get; set; }
........
}
and use this code for Db context
modelBuilder.Entity<Response>(entity =>
{
entity.HasOne(d => User)
.WithMany(p => p.Responses)
.HasForeignKey(d => d.UserId);
entity.HasOne(d => d.Question)
.WithMany(p => p.Responses)
.HasForeignKey(d => d.QuestionId;
});
I could solve it:
public class AppUser : IdentityUser<int, AppUserLogin, AppUserRole, IdentityUserClaimBase>, ICRMRepository, IEditableEntity, IEntityBase
{
public ICollection<Response> Responses { get; set; }
}
public class Question
{
public int Id { get; set; }
public string TextQuestion { get; set; }
public ICollection<Response> Responses { get; set; }
}
public class Response
{
public int Id { get; set; }
***public int AppUserId { get; set; }***
public int QuestionId { get; set; }
public virtual AppUser AppUser { get; set; }
public virtual Question Question { get; set; }
public string Answer { get; set; }
}
db context:
public DbSet<Question> Questions { get; set; }
public DbSet<Response> Responses { get; set; }
EF6 understand what I wanted
Related
I have problem with my current model snapshot.
This is part of my model:
public class SalaryInfo
{
public Guid Id { get; set; }
public double SalaryRate { get; set; }
public string Description { get; set; }
public UserProfile UserProfile { get; set; }
public Guid UserProfileId { get; set; }
}
public class RoleBasedSalaryInfo : SalaryInfo
{
public Roles Role { get; set; }
}
public class UserProfile
{
public Guid Id { get; set; }
public Roles Role { get; set; }
public Account User { get; set; }
public Guid UserId { get; set; }
}
public class EmployeeProfile : UserProfile
{
public SalaryInfo OfferingInfo { get; set; }
}
public class LegalEntityProfile : UserProfile
{
public ICollection<RoleBasedSalaryInfo> HiringInfo { get; set; }
public bool IsLegalEntity { get; set; }
}
Roles and Account are not important in this case.
So, in my migration I have
modelBuilder.Entity<SalaryInfo>(builder =>
{
builder.HasDiscriminator<string>("Discriminator")
.HasValue<SalaryInfo>(nameof(SalaryInfo))
.HasValue<RoleBasedSalaryInfo>(nameof(RoleBasedSalaryInfo));
});
but in snapshot I get:
modelBuilder.Entity("EntityModel.Profiles.AuxiliaryClasses.EmployeeProfile", b =>
{
b.HasBaseType("EntityModel.Profiles.BaseProfiles.UserProfile");
b.Property<Guid?>("OfferingInfoId").HasColumnType("uniqueidentifier");
b.HasIndex("OfferingInfoId");
b.HasDiscriminator().HasValue(998);
});
modelBuilder.Entity("EntityModel.Profiles.AuxiliaryClasses.LegalEntityProfile", b =>
{
b.HasBaseType("EntityModel.Profiles.BaseProfiles.UserProfile");
b.Property<bool>("IsLegalEntity")
.HasColumnType("bit");
b.HasDiscriminator().HasValue(999);
});
modelBuilder.Entity("EntityModel.Profiles.AuxiliaryClasses.RoleBasedSalaryInfo", b =>
{
b.HasBaseType("EntityModel.Profiles.AuxiliaryClasses.SalaryInfo");
b.Property<Guid?>("LegalEntityProfileId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Role")
.HasColumnType("int");
b.HasIndex("LegalEntityProfileId");
b.HasDiscriminator().HasValue("RoleBasedSalaryInfo");
});
modelBuilder.Entity("EntityModel.Profiles.AuxiliaryClasses.EmployeeProfile", b =>
{
b.HasOne("EntityModel.Profiles.AuxiliaryClasses.SalaryInfo", "OfferingInfo")
.WithMany()
.HasForeignKey("OfferingInfoId");
b.Navigation("OfferingInfo");
});
modelBuilder.Entity("EntityModel.Profiles.AuxiliaryClasses.RoleBasedSalaryInfo", b =>
{
b.HasOne("EntityModel.Profiles.AuxiliaryClasses.LegalEntityProfile", null)
.WithMany("HiringInfo")
.HasForeignKey("LegalEntityProfileId");
});
I really cannot understand of reason why LegalEntityProfileId and OfferingInfoId were added by migration. I supposed that I would get .HasForeighKey("UserProfileId") as a FK.
What should I do to get this "behaviour" (with UserProfileId as a FK)?
Thank you.
I need to create this tables:
Step (ID, Name)
Action (ID, Name)
StepActions(IdStep, IdAction, NextStep)
In Entity Framework:
public class Step
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<StepActions> StepActions { get; set; }
}
public class Action
{
public int Id { get; set; }
public virtual ICollection<StepActions> StepActions{ get; set; }
}
public class StepActions
{
public virtual Action Action { get; set; }
public virtual Step Step { get; set; }
public int Id { get; set; }
public int ActionID { get; set; }
public int StepID { get; set; }
public int NextStepID { get; set; }
}
I can create many-to-many relationship, but I don't know how to add relatioship for NextStep.
Thanks
Use these classes:
public partial class Step
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty(nameof(StepAction.NexStep))]
public virtual ICollection<StepAction> StepActionNexSteps { get; set; }
[InverseProperty(nameof(StepAction.Step))]
public virtual ICollection<StepAction> StepActionSteps { get; set; }
}
public partial class Action
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty(nameof(StepAction.Action))]
public virtual ICollection<StepAction> StepActions { get; set; }
}
public partial class StepAction
{
[Key]
public int Id { get; set; }
public int StepId { get; set; }
public int ActionId { get; set; }
public int NexStepId { get; set; }
[ForeignKey(nameof(StepId))]
[InverseProperty("StepActionSteps")]
public virtual Step Step { get; set; }
[ForeignKey(nameof(ActionId))]
[InverseProperty("StepActions")]
public virtual Action Action { get; set; }
[ForeignKey(nameof(NexStepId))]
[InverseProperty("StepActionNexSteps")]
public virtual Step NexStep { get; set; }
}
and this dbcontext:
public partial class StepsContext : DbContext
{
public StepsContext()
{
}
public StepsContext(DbContextOptions<StepsContext> options)
: base(options)
{
}
public virtual DbSet<Action> Actions { get; set; }
public virtual DbSet<Step> Steps { get; set; }
public virtual DbSet<StepAction> StepActions { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<StepAction>(entity =>
{
entity.HasOne(d => d.Action)
.WithMany(p => p.StepActions)
.HasForeignKey(d => d.ActionId)
.OnDelete(DeleteBehavior.ClientSetNull);
entity.HasOne(d => d.NexStep)
.WithMany(p => p.StepActionNexSteps)
.HasForeignKey(d => d.NexStepId)
.OnDelete(DeleteBehavior.ClientSetNull);
entity.HasOne(d => d.Step)
.WithMany(p => p.StepActionSteps)
.HasForeignKey(d => d.StepId)
.OnDelete(DeleteBehavior.ClientSetNull);
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
I dont know alot of English Lang But I will try...
so i have this error
Introducing FOREIGN KEY constraint 'FK_Conversation_User_Users_UserID' on table 'Conversation_User' may cause
cycles or multiple cascade paths.
Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
and my code is:
AppDB:
public class AppDB : DbContext
{
public AppDB() : base() { }
public AppDB(DbContextOptions<AppDB> options) : base(options) { }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"Server=(LocalDB)\MSSQLLocalDB;Database=TetraMessangerDB;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Conversation_User>().HasKey(cu => new { cu.ConversationID, cu.UserID });
modelBuilder.Entity<Message_Media>().HasKey(mm => new { mm.MediaID, mm.MessageID });
modelBuilder.Entity<Participant>().HasKey(p => new { p.UserID, p.GroupID });
}
public DbSet<User> Users { get; set; }
public DbSet<Conversation_User> Conversation_User { get; set; }
public DbSet<Conversation> Conversation { get; set; }
}
User:
public class User
{
public User()
{
Participants = new List<Participant>();
SenMessages = new List<Message>();
ResMessages = new List<Message>();
}
public int UserID { get; set; }
public string Name { get; set; }
public string Password { get; set; }
public string Bio { get; set; }
public string EMail { get; set; }
public string UserName { get; set; }
public bool Activate { get; set; }
public int MediaID { get; set; }
public virtual Media Media { get; set; }
public virtual UserStatus UserStatus { get; set; }
public virtual List<Participant> Participants { get; set; }
[InverseProperty("SenderUser")]
public virtual List<Message> SenMessages { get; set; }
[InverseProperty("ReciverUser")]
public virtual List<Message> ResMessages { get; set; }
public virtual List<Conversation_User> Conversation_User { get; set; }
}
Conversation:
public class Conversation
{
public Conversation()
{
Conversation_User = new List<Conversation_User>();
}
public int ConversationID { get; set; }
public DateTime StartDate { get; set; }
public int MediaID { get; set; }
public virtual Media Media { get; set; }
public virtual List<Conversation_User> Conversation_User { get; set; }
}
Conversation_User:
public class Conversation_User
{
public int ConversationID { get; set; }
public virtual Conversation Conversation { get; set; }
public int UserID { get; set; }
public virtual User User { get; set; }
}
so I see alot of same quastion but i dont understand ...
i dont have multiple path so why i get this error.
can some body explain this.
Note: I have alot of entitys with the same problem in Many-To-Many Relationship but if i can solve this, I will understand how to solve thim.
and thanks for helping me.
Edit: I tried this but still getting the same
modelBuilder.Entity<Conversation_User>()
.HasOne(pt => pt.User)
.WithMany(p => p.Conversation_User)
.HasForeignKey(pt => pt.UserID)
.IsRequired()
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Conversation_User>()
.HasOne(pt => pt.Conversation)
.WithMany(p => p.Conversation_User)
.HasForeignKey(pt => pt.ConversationID)
.IsRequired()
.OnDelete(DeleteBehavior.NoAction);
I have some classes:
public class Values : Entity
{
[Key]
public int Values_ID { get; set; }
[Required]
public string Values_Name { get; set; }
[Required]
public int ValuesNumeric { get; set; }
public virtual ICollection<ValuesMetrics> ValuesMetrics { get; set; }
}
public class GQMetric : Entity
{
[Key]
public int GQMetric_ID { get; set; }
[Required]
public string GQMetricName { get; set; }
[Required]
public int Importance_ID { get; set; }
public virtual List<GQMetricsQuestions> GQMetricsQuestions { get; set; }
public virtual ICollection<ValuesMetrics> ValuesMetrics { get; set; }
public virtual ImportanceScale ImportanceScale { get; set; }
}
I need to create many-to-many relationship to my own created class ValuesMetrics, not to automatically generated table by entity framework. I have tried a lot of solutions here, here and here but none of it did not work. Eventually, I did this:
public class ValuesMetrics : Entity
{
public int GQMetric_ID { get; set; }
public int Value_ID { get; set; }
public virtual GQMetric GQMetric { get; set; }
public virtual Values Values { get; set; }
}
FluentAPI:
modelBuilder.Entity<ValuesMetrics>()
.HasKey(c => new { c.GQMetric_ID, c.Value_ID });
modelBuilder.Entity<GQMetricsQuestions>()
.HasKey(c => new { c.GQMetric_ID, c.Question_ID });
but created table (ValuesMetrics) have an excessive relationship (GQMetrics_GQMetric_ID). I need only two primary keys from Values and GQMetrics tables
Can you advice me how to solve this problem? Thanks for any help!
Applied #Esteban 's solution from the link already referenced by you: Create code first, many to many, with additional fields in association table
Basically I did the following three changes:
Used POCO entities instead of inheriting from Entity class
Removed EF attributes, since we'll be using fluent API anyway
Changed fluent API configuration
Resulting code:
public class MyContext : DbContext
{
public DbSet<Values> Values { get; set; }
public DbSet<GQMetric> GqMetric { get; set; }
public DbSet<ValuesMetrics> ValuesMetrics { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Values>().HasKey(values => values.Values_ID);
modelBuilder.Entity<GQMetric>().HasKey(metric => metric.GQMetric_ID);
modelBuilder
.Entity<ValuesMetrics>()
.HasKey(valuesMetrics => new
{
valuesMetrics.Value_ID,
valuesMetrics.GQMetric_ID
});
modelBuilder
.Entity<ValuesMetrics>()
.HasRequired(valuesMetrics => valuesMetrics.Values)
.WithMany(valueMetrics => valueMetrics.ValuesMetrics)
.HasForeignKey(valueMetrics => valueMetrics.Value_ID);
modelBuilder
.Entity<ValuesMetrics>()
.HasRequired(valuesMetrics => valuesMetrics.GQMetric)
.WithMany(valueMetrics => valueMetrics.ValuesMetrics)
.HasForeignKey(valueMetrics => valueMetrics.GQMetric_ID);
base.OnModelCreating(modelBuilder);
}
}
public class Values
{
public int Values_ID { get; set; }
public string Values_Name { get; set; }
public int ValuesNumeric { get; set; }
public virtual ICollection<ValuesMetrics> ValuesMetrics { get; set; }
}
public class GQMetric
{
public int GQMetric_ID { get; set; }
public string GQMetricName { get; set; }
public virtual ICollection<ValuesMetrics> ValuesMetrics { get; set; }
}
public class ValuesMetrics
{
public int GQMetric_ID { get; set; }
public int Value_ID { get; set; }
public virtual GQMetric GQMetric { get; set; }
public virtual Values Values { get; set; }
}
I have 3 classes in my model as you can see below.
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string UserName { get; set; }
public ICollection<MartialArtUserProfile> MartialArtUserProfiles { get; set; }
}
[Table("MartialArt")]
public class MartialArt
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string IconPath { get; set; }
public string ImagePath { get; set; }
public ICollection<MartialArtUserProfile> MartialArtUserProfiles { get; set; }
}
public class MartialArtUserProfile
{
public int UserProfileId { get; set; }
public UserProfile UserProfile { get; set; }
public int MartialArtId { get; set; }
public MartialArt MartialArt { get; set; }
}
And I have a configuration class for many to many relationship as below:
public class MartialArtUserProfileConfiguration : EntityTypeConfiguration<MartialArtUserProfile>
{
public MartialArtUserProfileConfiguration()
{
HasKey(a => new { a.MartialArtId, a.UserProfileId });
HasRequired(a => a.MartialArt)
.WithMany(s => s.MartialArtUserProfiles)
.HasForeignKey(a => a.MartialArtId)
.WillCascadeOnDelete(false);
HasRequired(a => a.UserProfile)
.WithMany(p => p.MartialArtUserProfiles)
.HasForeignKey(a => a.UserProfileId)
.WillCascadeOnDelete(false);
}
}
After defining my entities an relation when I try to run Update-Database in Package Manager Console, it says:
One or more validation errors were detected during model generation:
\tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'MartialArtUserProfile' has no key defined. Define the key for this EntityType.
\tSystem.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'MartialArtUserProfiles' is based on type 'MartialArtUserProfile' that has no keys defined.
What am I doing wrong?
Thanks in advance,
If I understand you are simply trying to create a many to many with a transitive table. If so this is another way to approach this. Use Fluent API to map as below. You can change the UserProfileToMartialArt to whatever you want the table name to be. Instead of creating the MartialArtUserProfile model let EF create the middle ground for you. This also specifies your keys which should get you around the error.
modelBuilder.Entity<UserProfile>()
.HasMany(b => b.MartialArts)
.WithMany(a => a.UserProfiles)
.Map(m => m.MapLeftKey("MartialArtId")
.MapRightKey("UserProfileId")
.ToTable("UserProfileToMartialArt"));
In MartialArts Model put
public IList<UserProfile> UserProfiles { get; set; }
In UserProfile Model put
public IList<MartialArt> MartialArts { get; set; }
Try doing it like this:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string UserName { get; set; }
[InverseProperty("UserProfiles")]
public IList<MartialArt> MartialArts { get; set; }
}
[Table("MartialArt")]
public class MartialArt
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string IconPath { get; set; }
public string ImagePath { get; set; }
[InverseProperty("MartialArts")]
public IList<UserProfile> UserProfiles { get; set; }
}
In EntityFramework 6.1, you don't need to do any of this - just add collections of the two types to each class and everything falls into place.
public class UserProfile {
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<MartialArt> MartialArts { get; set; }
public UserProfile() {
MartialArts = new List<MartialArt>();
}
}
public class MartialArt {
public int Id { get; set; }
public string Name { get; set; }
// *snip*
public virtual ICollection<UserProfile> UserProfiles { get; set; }
public MartialArt() {
UserProfiles = new List<UserProfile>();
}
}