Cannot use WithMany in Entity Framework Fluent API - asp.net

I Can't use WithMany for many-to-many connection. I tried everything, and I have not idea what tha problem it could be. Please help if you have some axperience about it.
I have two models "Drink" and "DrinkCategory". every drink could have many categories, so I need many-to-many relationship.
Here is first model "Drink":
public class Drink
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
[Required]
public int DrinkId { get; set; }
[Required]
public int DrinkIngredientId { get; set; }
public string DrinkName { get; set; }
public virtual DrinkIngredient DrinkIngredients { get; set; }
public virtual ICollection<DrinkCategory> DrinkCategories { get; set; }
}
It is second model "DrinkCategorie":
public class DrinkCategory
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
[Required]
public int DrinkCategoryId { get; set; }
public string DrinkCategoryName { get; set; }
public int? ParentDrinkCategoryId { get; set; }
public virtual ICollection<Drink> Drinks { get; set; }
}
Here is my DBContext:
public class EatAndDrinkDbContext : DbContext
{
public EatAndDrinkDbContext(DbContextOptions<EatAndDrinkDbContext> options) : base(options) { }
public EatAndDrinkDbContext() { }
public DbSet<Drink> Drinks { get; set; }
public DbSet<DrinkCategory> DrinkCategories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Drink>()
.HasMany(c => c.DrinkCategories)
.WithMany(i => i.Drinks)
.Map(t => t.MapLeftKey("DrinkId")
.MapRightKey("DrinkCategoryId")
.ToTable("DrinkDrinkCategory"));
base.OnModelCreating(modelBuilder);
}
}

Related

EF Core 6 Many to many table after scaffold

I've made a dotnet ef scaffold from database and the classes generated were:
public partial class Course
{
public int Id { get; set; }
public string? Description { get; set; }
}
public partial class Student
{
public int Id { get; set; }
public string? Name { get; set; }
}
public partial class StudentCourse
{
public int? IdStudent { get; set; }
public int? IdCourse { get; set; }
public virtual Student? IdStudentNavigation { get; set; }
public virtual Course? IdCourseNavigation { get; set; }
}
I want to get a List of Student where id of Course is X
I've tried _context.Student.Include("StudentCourse").Where(x=>x.Any(....) but Intellisense does not accept "Any" function.
How can i get this ?
Any(...) is a method provided by Enumerable class so you can not use it on a single Student (which is obviously not an Enumerable object).
Your configuration of many-to-many relationship is maybe missing some lines, here is my suggestion:
public partial class Course
{
public int Id { get; set; }
public string? Description { get; set; }
public List<StudentCourse> StudentCourses { get; set; }
}
public partial class Student
{
public int Id { get; set; }
public string? Name { get; set; }
public List<StudentCourse> StudentCourses { get; set; }
}
public partial class StudentCourse
{
public int? IdStudent { get; set; }
public int? IdCourse { get; set; }
public virtual Student? StudentNavigation { get; set; }
public virtual Course? CourseNavigation { get; set; }
}
In Context file:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<StudentCourse>()
.HasOne(sc => sc.StudentNavigation)
.WithMany(s => s.StudentCourses)
.HasForeignKey(sc => sc.IdStudent);
modelBuilder.Entity<StudentCourse>()
.HasOne(sc => sc.CourseNavigation)
.WithMany(c => c.StudentCourses)
.HasForeignKey(sc => sc.IdCourse);
}
Finally, your query could be:
IEnumerable<Student> students = await _context.Students
.Include(s => s.StudentCourses)
.Where(s => s.StudentCourses.Any(sc => sc.IdCourse == X)))
I am just taking your code as example but this is not a way you design entity in EF core.
Try following though.
var students
=_context.StudentCourse.Include("IdStudentNavigation").Where(x=>x.IdCourse == 1).Select(x => x.IdStudentNavigation).ToList();
Replace one with your course id.

Entity Framework Code first, relation between models

Is there someone who will listen to me and help me solve my problem?
I have 3 classes (Product, Lot and Rem):
Each Product has many Lot and each Lot has many Rem.
public class Product {
public int id { get; set; }
public string name { get; set; }
}
public class Lot {
public int id { get; set; }
public decimal price { get; set; }
}
public class Rem {
public int id { get; set; }
public string note { get; set; }
}
From what you described above this is a simple way for related entities in EF.
public class Product {
public int id { get; set; }
public string name { get; set; }
public Lot LotId {get; set; }
public ICollection<Lot> Lots { get; set; }
}
public class Lot {
public int id { get; set; }
public decimal price { get; set; }
public Product ProductId {get; set; }
public Product Product {get; set; }
public Rem RemId {get; set; }
public ICollection<Rem> Rems { get; set; }
}
public class Rem {
public int id { get; set; }
public string note { get; set; }
public Lot LotId {get; set; }
public Lot Lot { get; set; }
}
And the dbcontext class
public class AppDbContext: DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options): base(options)
{
}
public DbSet<Product> Products { get; set; }
public DbSet<Lot> Lots { get; set; }
public DbSet<Rem> Rems { get; set; }
}
You can find further explanation about relationships in EF from relationships in EF

EF core and creating a many to many table. Creates extra field. Why ?

Why is there a UserProgramRefProgramCharacteristics.RefProgramCharacteristicsId field??? There should only be 2 fields not 3. Right? Below are the 3 classes and the OnModelCreating that is needed to create a many to many table
public class RefProgramCharacteristic
{
public int Id { get; set; }
public string ProgramCharacteristic { get; set; }
public List<UserProgramRefProgramCharacteristic> UserProgramRefProgramCharacteristics { get; set; }
// public ICollection<UserProgram> userPrograms { get; } = new List<UserProgram>();
// public virtual ICollection<UserProgram> UserPrograms { get; set; }
}
public class UserProgram
{
public int Id { get; set; }
//UserProgramSaved
public bool MyList { get; set; }
public float MyPriorityRating { get; set; }
public int Similarity { get; set; }
public bool Compare { get; set; }
//UserProgramSimilarity
public int OverallSimilarityScore { get; set; }
public int DeltaProfileElement1_WorkExp { get; set; }
public int DeltaProfileElement2_VolExp { get; set; }
public int DeltaProfileElement3_ResExp { get; set; }
public int DeltaProfileElement4_Pubs { get; set; }
public int DeltaProfileElement5_Step1 { get; set; }
public int DeltaProfileElement6_Step2ck { get; set; }
public int DeltaProfileElement7_Aoa { get; set; }
public int DeltaProfileElement8_Nspecialties { get; set; }
public int DeltaProfileElement9_PercentApps { get; set; }
//UserComparisonSaved
// public RefProgramCharacteristic RefProgramCharacteristic { get; set; }
public string RefProgramCharacteristicList { get; set; }
public string ApplicationUserId { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public int MedicalProgramId { get; set; }
public RefProgramDetailData MedicalProgram { get; set; }
public List<UserProgramRefProgramCharacteristic> UserProgramRefProgramCharacteristics { get; set; }
// public ICollection<RefProgramCharacteristic> RefProgramCharacteristics { get; } = new List<RefProgramCharacteristic>();
// public virtual ICollection<RefProgramCharacteristic> RefProgramCharacteristics { get; set; }
}
public class UserProgramRefProgramCharacteristic
{
// public int Id { get; set; }
public int UserProgramId { get; set; }
public UserProgram UserProgram { get; set; }
public int RefProgramCharacteristicsId { get; set; }
public RefProgramCharacteristic RefProgramCharacteristic { get; set; }
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<UserProgramRefProgramCharacteristic>()
.HasKey(t => new { t.UserProgramId, t.RefProgramCharacteristicsId });
base.OnModelCreating(builder);
}
Why is there a UserProgramRefProgramCharacteristics.RefProgramCharacteristicsId field?
Because you are telling EF Core to create such field here:
public int RefProgramCharacteristicsId { get; set; }
// ^
While the navigation property is called RefProgramCharacteristic (no s). And by EF Core conventions:
If the dependent entity contains a property named <primary key property name>, <navigation property name><primary key property name>, or <principal entity name><primary key property name> then it will be configured as the foreign key.
RefProgramCharacteristicsId does not match any of these rules, so EF Core creates a shadow FK property with default name RefProgramCharacteristicId.
Either rename the property to RefProgramCharacteristicId (best), or map it explicitly using ForeignKey data annotation:
[ForeignKey(nameof(RefProgramCharacteristicsId))]
public RefProgramCharacteristic RefProgramCharacteristic { get; set; }
or
[ForeignKey(nameof(RefProgramCharacteristic))]
public int RefProgramCharacteristicsId { get; set; }
or using HasForeignKey fluent API:
builder.Entity<UserProgramRefProgramCharacteristic>()
.HasOne(e => e.RefProgramCharacteristic)
.WithMany(e => e.UserProgramRefProgramCharacteristics)
.HasForeignKey(e => e.RefProgramCharacteristicsId);

MVC 5 Complex View Model binding is not working

public class CreateProjeModel
{
public Proje Proje { get; set; }
public List<GeometryModel> GeometryList { get; set; }
public CreateProjeModel()
{
Proje = new Proje();
GeometryList = new List<GeometryModel>();
}
}
public class GeometryModel
{
public List<PointModel> PointList { get; set; }
public GeometryModel()
{
PointList = new List<PointModel>();
}
}
public class PointModel
{
public int X { get; set; }
public int Y { get; set; }
}
public class Proje : EntityBase
{
public int FirmaId { get; set; }
public int IlId { get; set; }
public int? IlceId { get; set; }
public int PlanTurId { get; set; }
public int EtudTurId { get; set; }
public int EtudAmacId { get; set; }
public int DilimId { get; set; }
public string Aciklama { get; set; }
public virtual Firma Firma { get; set; }
public virtual IL Il { get; set; }
public virtual ILCE Ilce { get; set; }
public virtual PlanTur PlanTur { get; set; }
public virtual EtudTur EtudTur { get; set; }
public virtual EtudAmac EtudAmac { get; set; }
public virtual Dilim Dilim { get; set; }
}
I have a complex model named CreateProjeModel. I'm using 'for' to loop collection properties and binding like below:
#Html.TextBoxFor(m => m.GeometryList[i].PointList[j].X)
Action is like below:
[HttpPost]
public async Task<ActionResult> Create(CreateProjeModel proje)
{
//ToDo
return View(proje);
}
Posted data is below:
When it comes to action, GeometryList is empty and Proje's properties are not set to post values. Where am I doing wrong?
Your problem is that your CreateProjeModel model has a property named Proje, but the parameter of your Create() method is also named proje. Your need to change the method signature to (say)
public async Task<ActionResult> Create(CreateProjeModel model)
where the parameter name is not the same as the nae of one of your properties

EF6 MVC5 Setting a 1-1 Relationship

I have got my application up and running using Code first, I am trying to set a 1-1 relationship but when I update-database I get the error "SupplyPointId: Name: Each property name in a type must be unique. Property name 'SupplyPointId' is already defined."
I've tried removing the existing index constraint on SupplyPointAddress.SupplyPointId and that does not help. In the other table its the PK. Any comments really appreciated
public partial class SupplyPoint
{
[Key]
//[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int SupplyPointId { get; set; }
public string SPID { get; set; }
public string SupplyPointName { get; set; }
public int SupplyPointTypeId { get; set; }
public DateTime SupplyPointEffectiveDateTime { get; set; }
public string GazateerRef { get; set; }
public virtual SupplyPointType SupplyPointType { get; set; }
//[ForeignKey("SupplyPointId")]
public virtual SupplyPointAddress SupplyPointAddress { get; set; }
}
public partial class SupplyPointAddress
{
[Key]
//[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int SupplyPointAddressId { get; set; }
public int SupplyPointId { get; set; }
public string D5001_FreeDescriptor { get; set; }
public string D5002_SubBuildingName { get; set; }
public string D5003_BuildingName { get; set; }
public string D5004_BuildingNumber { get; set; }
public string D5005_DependentThoroughfareName { get; set; }
public string D5006_DependentThoroughfareDescriptor { get; set; }
public string D5007_ThoroughfareName { get; set; }
public string D5008_ThoroughfareDescriptor { get; set; }
public string D5009_DoubleDependentLocality { get; set; }
public string D5010_DependentLocality { get; set; }
public string D5011_PostTown { get; set; }
public string D5012_County { get; set; }
public string D5013_Postcode { get; set; }
public virtual SupplyPoint SupplyPoint { get; set; }
}
public System.Data.Entity.DbSet<AscendancyCF.Models.SupplyPoint> SupplyPoints { get; set; }
public System.Data.Entity.DbSet<AscendancyCF.Models.SupplyPointAddress> SupplyPointAddresses { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<SupplyPointAddress>()
.HasOptional<SupplyPoint>(u => u.SupplyPoint)
.WithRequired(c => c.SupplyPointAddress).Map(p => p.MapKey("SupplyPointId"));
base.OnModelCreating(modelBuilder);
}
I moved the foreign key into SupplyPoint table so that the foreign key was being defined as SupplyPointAddressId in SupplyPoint. This worked and allows me to do SupplyPoint.SupplyPointAddress in resultant model
Since you're testing with a real DB. Use some of the
Database Initialization Strategies in Code-First:
public class SchoolDBContext: DbContext
{
public SchoolDBContext(): base("SchoolDBConnectionString")
{
Database.SetInitializer<SchoolDBContext>(new CreateDatabaseIfNotExists<SchoolDBContext>());
//Database.SetInitializer<SchoolDBContext>(new DropCreateDatabaseIfModelChanges<SchoolDBContext>());
//Database.SetInitializer<SchoolDBContext>(new DropCreateDatabaseAlways<SchoolDBContext>());
//Database.SetInitializer<SchoolDBContext>(new SchoolDBInitializer());
}
public DbSet<Student> Students { get; set; }
public DbSet<Standard> Standards { get; set; }
}
(Excerpt from this site)
It is pretty self explanatory.
If there's already a DB created, it just DROPs it.
Happy coding!

Resources