Reputation: 6265
I have a table restaurant. A restaurant can have multiple specialties. And specialties are for example chinees, spahnish, greeks, etc.
Restaurant table/class:
[Table("Restaurant")]
public class Restaurant
{
[Key]
[Column(Order = 0)]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(40)]
[Column(Order = 2)]
public string Name { get; set; }
[MaxLength(1000)]
[Column(Order = 6)]
public string Comments { get; set; }
public virtual ICollection<Specialties> Specialties { get; set; }
}
And this is my specialties table/class:
public enum Specialty
{
Chinees = 0,
Spanish = 1,
Etc.. = 2,
}
[Table("Specialties")]
public class Specialties
{
[Key]
[Column(Order = 0)]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[Column(Order = 1)]
public Specialty Specialty { get; set; }
//[Required]
[MaxLength(20)]
[Column(Order = 2)]
public string Name { get; set; }
public virtual ICollection<Restaurant> Restaurant { get; set; }
}
The specialties table is pre-filled with data.
This is my table/class for the many to many relationship:
[Table("RestaurantSpecialties")]
public class RestaurantSpecialties
{
[Key]
public int RestaurantId { get; set; }
[Key]
public int SpecialtyId { get; set; }
[ForeignKey("RestaurantId")]
public virtual Restaurant Restaurant{ get; set; }
[ForeignKey("SpecialtyId")]
public virtual Specialties Specialty { get; set; }
}
With Fluent Api
I tried to define the model like this:
// Primary keys
modelBuilder.Entity<Restaurant>().HasKey(q => q.Id);
modelBuilder.Entity<Specialties>().HasKey(q => q.Id);
// Relationship
modelBuilder.Entity<Restaurant>()
.HasMany(q => q.Specialties)
.WithMany(q => q.Restaurant)
.Map(q =>
{
q.ToTable("RestaurantSpecialty");
q.MapLeftKey("RestaurantId");
q.MapRightKey("SpecialtyId");
});
And in my Seed function i'm seeding data like this:
context.Specialties.AddOrUpdate(
p => p.Specialty,
new Specialties { Specialty = Specialty.Chinees, Name = "Chinees" },
new Specialties { Specialty = Specialty.Spanish, Name = "Spanish" },
);
ICollection<Specialties> lstSpecialties = new List<Specialties>();
lstSpecialties.Add(context.Specialties.FirstOrDefault(x => x.Name == "Chinees"));
context.Restaurants.AddOrUpdate(
p => p.Name,
new Restaurant{ Name = "Ctr test1", Specialties = lstSpecialties, Comments = "sfasd" },
new Restaurant{ Name = "Ctr test2", Specialties = lstSpecialties, Comments = "asd" },
);
But my table RestaurantSpecialties doesn't contain anything. I was expecting to see Id's of both tables.
What am I doing wrong?
[EDIT]
The enum has been renamed from 'Specialty' to 'RestaurantSpecialty' like Gert suggested to do (just the rename part, not the actual name).
The plural class 'Specialties' has also been renamed to 'Specialty'. Also because Gert suggested it.
The join table has also been removed from the model. The Fluent Api
part in my original post has been updated accordingly.
Catering(s) has been renamed to Restaurant(s) which i forgot to do so in the beginning. So to avoind confusions i've done this too in my original code post.
context.Specialties.AddOrUpdate(
new Specialty { CateringSpecialty = RestaurantSpecialty.Chinese, Name = "Chinese" },
new Specialty { CateringSpecialty = CateringSpecialty.Greeks, Name = "Greeks" },
);
var aSpecialty = context.Specialties.FirstOrDefault(x => x.Name == "Chinese");
var restaurant1 = context.Restaurants.Include(c => c.Specialties).FirstOrDefault(x => x.Name == "Ctr test1");
if (restaurant1 == null)
{
restaurant1 = new Restaurant
{
Name = "Ctr test4",
Specialties = new List<Specialty> { aSpecialty },
Comments = "testtttttttt"
};
context.Restaurants.Add(restaurant1);
}
else
{
if (!restaurant1.Specialties.Any(s => s.Id == aSpecialty.Id))
restaurant1.Specialties.Add(aSpecialty);
restaurant1.Name = "Ctr test4";
restaurant1.Comments = "testtttt";
}
Upvotes: 1
Views: 1842
Reputation: 177173
Try to add/update manually. I suspect that the AddOrUpdate
method does not support updating a full object graph of related entities. Probably it supports adding related entities together with its parent entity if the parent entity doesn't exist yet. But if the "Chinees" specialty was already in the database without related entities the relationships possibly don't get updated.
A "manual update" would look like this:
context.Specialties.AddOrUpdate(
p => p.Specialty,
new Specialties { Specialty = Specialty.Chinees, Name = "Chinees" },
new Specialties { Specialty = Specialty.Spanish, Name = "Spanish" },
);
var chineesSpecialty = context.Specialties
.FirstOrDefault(x => x.Name == "Chinees");
var catering1 = context.Caterings.Include(c => c.Specialties)
.FirstOrDefault(x => x.Name == "Ctr test1");
if (catering1 == null)
{
catering1 = new Catering
{
Name = "Ctr test1",
Specialties = new List<Specialties> { chineesSpecialty },
Comments = "sfasd"
};
context.Caterings.Add(catering1);
}
else
{
if (!catering1.Specialties.Any(s => s.Id == chineesSpecialty.Id))
catering1.Specialties.Add(chineesSpecialty);
catering1.Comments = "sfasd";
}
// and the same for "Ctr test2"
This is also mentioned in this answer but it was during the early preview releases of Code-First Migrations, so I am not sure if this limitation still exists. But it would explain why you don't get entries in the relationship table.
Your mapping itself looks correct to me. (But as already recommended by Gert Arnold in the comments I would really remove the RestaurantSpecialties
entity which looks redundant and only complicates your model.)
Upvotes: 1