【问题标题】:Many2Many Relationships in Entiry Framework CoreEntity Framework Core 中的 Many2Many 关系
【发布时间】:2017-09-26 04:26:07
【问题描述】:

所以,在遵循@zadqvb8 在https://docs.microsoft.com/en-us/ef/core/modeling/relationships?hubRefSrc=email&utm_source=lfemail&utm_medium=email&utm_campaign=lfnotification#lf-content=177107930:682390858 中的善意建议后,我仍然无法完成这项工作。

Entity 中,在一侧 (A) 的一个实体和另一侧 (BCD...) 的多个不同实体之间建立和使用 Many2Many 关系,是否有人有真实的经验框架核心? (我们称结果表为“AB”)。

框架不支持开箱即用,并且解决方法不会产生在关系中创建的任何实际记录...

背景:标签是一侧的实体,另一侧是几个资产类别...我只是想为资产添加标签。所描述的解决方案不会在 (AB) 关系表中生成条目。

使用 SQLite,因为这是一个 UWP 应用...请不要讨厌。

--更新 2017-04-29 13:39 CET

非常感谢提供帮助。

为简单起见,我将发布在 ModelImage 和 ModelTag 之间创建 m2m 的代码:

public class ModelImage
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ModelImageId { get; set; }

    public List<ModelImageTag> Tags { get; set; }
}

public class ModelTag
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ModelTagId { get; set; }

    public List<ModelImageTag> Images { get; set; }
}

public class ModelImageTag
{
   public int ModelImageId { get; set; }
   public ModelImage ModelImage { get; set; }

   public int ModelTagId { get; set; }
   public ModelTag ModelTag { get; set; }
}

这些类还有更多,但我想这些属性就足够了

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<ModelImageTag>().HasKey(x => new { x.ModelImageId, x.ModelTagId });
    modelBuilder.Entity<ModelImageTag>().HasOne(x => x.ModelImage).WithMany(x => x.Tags).HasForeignKey(x => x.ModelTagId);
    modelBuilder.Entity<ModelImageTag>().HasOne(x => x.ModelTag).WithMany(x => x.Images).HasForeignKey(x => x.ModelImageId);
}

这是添加关系的部分:

ModelImage image = ....;
ModelTag tag = ...;

ModelImageTag iTag = new ModelImageTag { ModelImage = image, ModelTag = tag};
tag.Images.Add(iTag);
image.Tags.Add(iTag);

Context.SaveChanges();

我尝试在 ModelImageTag 或实体引用中设置 ID,没有结果。

我错过了什么?非常感谢任何建议。

【问题讨论】:

  • 你能发布你的实体和OnModelCreating()吗?
  • this页面有一个简单的例子
  • 我们无法帮助您修复我们看不到的代码。
  • 进行了编辑,请查看。
  • 我更喜欢语法modelBuilder.Entity&lt;ModelImage&gt;().HasMany(c =&gt; c.Tags).WithMany(i =&gt; i.Images).Map(t =&gt; t.MapLeftKey("ModelImageId).MapRightKey("ModelTagId").ToTable("ModelImageTag"));here。不要认为您需要 Images.Add 和 Tags.Add 行。

标签: c# entity-framework sqlite uwp


【解决方案1】:

首先,您为 ModelImageTag 实体创建的表提供了错误的 ForeignKey。如您所知,EFCore 目前不支持多对多关系。所以我们使用连接表并映射两个单独的一对多关系。

对于此代码行modelBuilder.Entity&lt;ModelImageTag&gt;().HasOne(x =&gt; x.ModelImage).WithMany(x =&gt; x.Tags).HasForeignKey(x =&gt; x.ModelTagId); 连接表ModelImageTag 将创建与ModelImage 的一对多关系,因此其外键应为ModelImageId,而不是ModelTagId。更新模型创建代码如下:

public class MyContext : DbContext
{
   public DbSet<ModelImage> ModelImages { get; set; }
   public DbSet<ModelTag> ModelTags { get; set; }         

   protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
   {
       optionsBuilder.UseSqlite("Filename=ModelImageDatabase.db");
   } 
   protected override void OnModelCreating(ModelBuilder modelBuilder)
   {
       modelBuilder.Entity<ModelImageTag>()
           .HasKey(x => new { x.ModelImageId, x.ModelTagId });
       modelBuilder.Entity<ModelImageTag>()
           .HasOne(x => x.ModelImage)
           .WithMany(x => x.Tags)
           .HasForeignKey(x => x.ModelImageId);
       modelBuilder.Entity<ModelImageTag>()
           .HasOne(x => x.ModelTag)
           .WithMany(x => x.Images)
           .HasForeignKey(x => x.ModelTagId);
   }
}

其次,在将更改保存到数据库之前,您没有代码 sn-p 将记录添加到数据库。

image.Tags.Add(iTag);
Context.ModelImages.Add(image);
Context.SaveChanges();

这是一个完整的示例代码,通过连接表 ModelImageTagModelImageModelTag 之间创建多对多关系,这可以帮助您更清楚地了解。

 var Context = new MyContext();
 ModelImage image = new ModelImage()
 {
     ModelImageId = 101,
     Tags = new List<ModelImageTag>()
 };
 ModelImage image2 = new ModelImage()
 {
     ModelImageId = 102,
     Tags = new List<ModelImageTag>()
 };
 ModelTag tag = new ModelTag()
 {
     ModelTagId = 201,
     Images = new List<ModelImageTag>()
 };
 ModelTag tag2 = new ModelTag()
 {
     ModelTagId = 202,
     Images = new List<ModelImageTag>()
 };
 ModelImageTag iTag = new ModelImageTag { ModelImage = image, ModelTag = tag };
 ModelImageTag iTag2 = new ModelImageTag { ModelImage = image, ModelTag = tag2 };
 ModelImageTag iTag3 = new ModelImageTag { ModelTag = tag, ModelImage = image2 };
 tag.Images.Add(iTag3);
 image.Tags.Add(iTag);
 image.Tags.Add(iTag2);
 Context.ModelImages.Add(image);
 Context.ModelImages.Add(image2);
 Context.ModelTags.Add(tag);
 Context.SaveChanges();

结果:

更多详情请参考this document。如果您仍有问题,请提供一个最小的重现项目。

【讨论】:

  • 嗨吴,终于有时间检查你的建议......宾果游戏,这里有两个问题。 1)外键,正如刚才所指出的,但这不是真正的问题。 2) 我没有创建 ModelImage.Tags。是的,35 年的软件开发,仍然没有正确地实例化一个新类。哈哈。所以当然 .Tags.Add 爆炸了。关于这一点,我可以在创建时在模型实体中实例化集合(这是我通常对我的类所做的,因此出现了这个错误,因为我偏离了我的通常做法)还是 EF 会抛出?
  • @J.H.我上传了完整的项目here请测试。如果仍有问题,请提供您的复现项目和测试环境。
  • @J.H.我刚刚看到你更新了你的 cmets。对不起,我对你现在问的有点困惑。你能详细说明一下吗?您现在可以成功运行您的项目吗?什么“不包含实例化 ModelImage.Tags”。什么意思?
  • 您好,这意味着当您实例化一个ModelImage时,您需要通过image.Tags = new List();来实例化一个Tags。我通常设计我的类,以便在创建类实例时实例化内部的任何集合。我不确定这是否适用于 EF 中的类...所以问题是:我可以为 ModelImage.Tags 声明一个构造函数,该构造函数在创建 ModelImage 实例时调用。还是 EF 不使用普通的类构造函数?
  • @J.H.在我看来,EF 与你如何构造函数没有关系。因此,在创建实例时添加 image.tags 或在创建实例后添加都可以,但要确保它具有正确的语法和结果。顺便说一句,如果我的回复对您有帮助,请您标记为已接受。
【解决方案2】:

您的代码:

ModelImage image = ....;
ModelTag tag = ...;

ModelImageTag iTag = new ModelImageTag { ModelImage = image, ModelTag = tag};
tag.Images.Add(iTag);
image.Tags.Add(iTag);

Context.SaveChanges();

更正的代码:

// in DbContext
DbSet<ModelImage> ModelImages;
DbSet<ModelTags> ModelTags;
DbSet<ModelImageTag> ModelImageTags;

// your code:

ModelImage image = ....;
ModelTag tag = ...;

ModelImageTag iTag = new ModelImageTag { ModelImage = image, ModelTag = tag};
tag.Images.Add(iTag);
image.Tags.Add(iTag);

// tell EF to add the above objects (without this, you got nothing)...
Context.ModelImages.Add(image);  // can also use AddRange()
Context.ModelTags.Add(tag);
Context.ModelImageTags.Add(iTag);

Context.SaveChanges();

【讨论】:

  • 谢谢亚当。实际上,我抛弃了 Normform 的整个概念,并将所有标签作为资产实体中的分隔字符串。比任何东西都快 EF...
猜你喜欢
  • 2022-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
  • 2023-01-25
  • 1970-01-01
  • 2019-08-07
相关资源
最近更新 更多