Code First关系一对多/多对多

时间:2013-06-18 08:50:43

标签: ef-code-first entity-framework-5 ef-migrations

我有一家餐厅。餐厅可以提供多种特色菜。特色菜是例如chinees,spahnish,greeks等。

餐厅桌/类:

[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; }
}

这是我的专业表/班级:

 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; }
    }

专业表预先填充了数据。

这是我的表/类,用于多对多的关系:

[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; }
    }

使用Fluent Api我试图像这样定义模型:

// 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");
    });

在我的种子功能中,我正在播种这样的数据:

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" },
  );

但我的餐厅RestaurantSpecialties不含任何东西。我期待看到两张桌子的Id。

我做错了什么?

[编辑]

enum已经从'Specialty'重命名为'RestaurantSpecialty',就像Gert建议做的那样(只是重命名部分,而不是实际名称)。

复数类'Specialties'也被重命名为'Specialty'。也因为格特建议。

联接表也已从模型中删除。我原始帖子中的Fluent Api部分已相应更新。

餐饮已更名为餐厅,我忘了在开始时这样做。因此,为了避免混淆,我在原始代码中也做了这个。

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";
 }

1 个答案:

答案 0 :(得分:1)

尝试手动添加/更新。我怀疑AddOrUpdate方法不支持更新相关实体的完整对象图。如果父实体尚不存在,它可能支持将相关实体与其父实体一起添加。但是,如果“Chinees”专业已经存在于没有相关实体的数据库中,则关系可能无法更新。

“手动更新”如下所示:

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"

这也提到in this answer,但它是在Code-First Migrations的早期预览版本中,所以我不确定这个限制是否仍然存在。但它可以解释为什么你不在关系表中获得条目。

您的映射本身对我来说是正确的。 (但正如Gert Arnold在评论中已经建议的那样,我真的会删除看起来多余的RestaurantSpecialties实体并且只会使你的模型复杂化。)