gpt4 book ai didi

c# - 使用实体配置与多个表的一对一/一关系

转载 作者:行者123 更新时间:2023-11-30 17:29:56 25 4
gpt4 key购买 nike

我处于一张 table 有两个一对无/一对关系的情况。如何使用 Entity Framework 代码优先来实现这一点?

我看过以下链接

  • https://www.safaribooksonline.com/library/view/programming-entity-framework/9781449317867/ch04s07.html
  • https://cpratt.co/0-1-to-1-relationships-in-entity-framework/
  • https://www.tektutorialshub.com/one-to-one-relationship-entity-framework/

  • 从本质上讲,从属端需要有一个与主端相同的主键。但是我厌倦了在没有确认和正确了解正在发生的事情的情况下,用不止一种一对无/一对关系来实现这一点。此外,我不确定如何构造语句,因为它没有传统的外键。

    我也看过 Configuring multiple 1 to 0..1 relationships between tables entity framework这让我不知所措。

    有关我的数据库图的相关部分,请参见下文:

    所以本质上,一个 Player不应该在没有 DKImage 的情况下保存,同样是 Product不应该在没有 DKImage 的情况下保存.

    以下是模型的代码: Players , Products , DKImages (我知道这是不正确的,我只是这样实现的,所以我可以生成数据库并显示图表)

    播放器
    public enum Positions { PG, SG, SF, PF, C }

    public class Player
    {
    [Key]
    [ForeignKey("Images")]
    public int PlayerID { get; set; }

    [Required]
    public string PlayerName { get; set; }

    [Required]
    public string PlayerLastName { get; set; }

    [Required]
    public int PlayerAge { get; set; }

    [Required]
    public Positions Position { get; set; }

    [Required]
    public bool Starter { get; set; }

    [Required]
    [Display(Name = "Active / Not Active")]
    public bool Status { get; set; }

    //Foreign Keys
    public int PlayerStatsID { get; set; }

    //Navigation Properties
    [ForeignKey("PlayerStatsID")]
    public virtual IQueryable<PlayerStats> PlayerStats { get; set; }
    public virtual DKImages Images { get; set; }
    }

    DKImages
    public class DKImages
    {
    [Key]
    public int ImageID { get; set; }
    [Required]
    public string ImageURL { get; set; }
    [Required]
    public DateTime DateUploaded { get; set; }

    //Foreign Keys
    [Required]
    public int CategoryID { get; set; }

    //Navigation Properties
    public virtual Products Products { get; set; }
    public virtual Category Category { get; set; }
    public virtual Player Player { get; set; }
    }

    产品
    public class Products
    {
    [ForeignKey("Images")]
    [Key]
    public int ProductID { get; set; }
    [Required]
    public string ProductName { get; set; }
    [Required]
    public DateTime DateAdded { get; set; }

    //Foreign Keys
    [Required]
    public int ProductTypeID { get; set; }

    //Navigation Properties
    [ForeignKey("ProductTypeID")]
    public virtual ProductType ProductType { get; set; }
    public virtual DKImages Images { get; set; }
    }

    编辑

    有人告诉我上面的代码是正确的。如果是这样,那么我如何使用上述代码创建 CRUD LINQ 语句(或任何构造 CRUD 语句的方法)。

    最佳答案

    你想要的在这里被称为polymorphic associations :具有一种类型的子实体的多个实体。它们通常用于评论、评论、文件等,通常应用于 1:n 关联。在您的情况下,存在多态 1:1 关联。基本上这些关联看起来像这样(使用更通用的名称):

    如何实现它们?
    Entity Framework 6
    在 EF6 中,这是个问题。 EF6 将 1:1 关联实现为共享主键:子键的主键也是其父键的外键。这意味着 Image.ID 上应该有两个 FK。 ,一指向Person.ID另一个指向 Product.ID .从技术上讲,这不是问题,但在语义上却是。两个父实体现在拥有相同的图像,或者换句话说,一个图像应该始终属于两个不同的父实体。在现实生活中,这是无稽之谈。
    解决方案可能是反转引用:
    enter image description here
    但现在还有另一个问题。所引用的实体称为主体,另一个实体是从属实体。在第二个图中,Image是主体,所以为了创建Person ,必须先插入其图像,然后该人复制其主键。这是违反直觉的,而且很可能也不切实际。如果图像是可选的,这是不可能的。
    尽管如此,由于在您的情况下您希望需要图像,让我展示如何在 EF6 中映射此关联。
    让我们以这个简单的模型为例:

    public class Person
    {
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual Image Image { get; set; }
    }

    public class Product
    {
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual Image Image { get; set; }
    }

    public class Image
    {
    public int ImgID { get; set; } // Named for distinction
    public string Url { get; set; }
    }
    所需的映射是:
    modelBuilder.Entity<Image>().HasKey(pd => pd.ImgID);
    modelBuilder.Entity<Person>().HasRequired(p => p.Image).WithRequiredDependent();
    modelBuilder.Entity<Product>().HasRequired(p => p.Image).WithRequiredDependent();
    如您所见, Image有两个必需的家属。也许这比两个必需的 parent 要好,但这仍然很奇怪。幸运的是,实际上这不是问题,因为 EF 不会验证这些关联。您甚至可以在没有“必需”依赖项的情况下插入图像。我不知道为什么 EF 不验证这一点,但在这里它派上用场。零件 WithRequiredDependent还不如是 WithOptional ,它对生成的数据模型没有影响,但至少这个映射传达了你的意图。
    另一种方法可能是 继承 .如 PersonProduct从一个基类继承该基类可以是与 Image 1:1 关联的主体.但是,我认为这是滥用设计模式。人和产品没有任何共同点。从设计的角度来看,它们没有理由成为一个继承树的一部分。
    因此,在 EF6 中我认为最可行的解决方案是使用第三种方案: 每个实体单独的图像表 .
    Entity Framework 核心
    在 EF-core 1:1 关联中,可以通过 EF6 方式实现,但也可以在依赖实体中使用单独的外键字段。这样做,多态情况如下所示:
    Image类是不同的:
    public class Image
    {
    public Image()
    { }
    public int ImgID { get; set; }
    public int? PersonID { get; set; }
    public int? ProductID { get; set; }
    public string Url { get; set; }
    }
    和映射:
    modelBuilder.Entity<Person>().Property(p => p.ID).UseSqlServerIdentityColumn();
    modelBuilder.Entity<Person>()
    .HasOne(p => p.Image)
    .WithOne()
    .HasForeignKey<Image>(p => p.PersonID);
    modelBuilder.Entity<Product>().Property(p => p.ID).UseSqlServerIdentityColumn();
    modelBuilder.Entity<Product>()
    .HasOne(p => p.Image)
    .WithOne()
    .HasForeignKey<Image>(p => p.ProductID);
    modelBuilder.Entity<Image>().HasKey(p => p.ImgID);
    观察可为空的外键。它们是必需的,因为图像属于 PersonProduct .这是这种设计的一个缺点。另一个是您需要为每个要拥有图像的新实体创建一个新的外键字段。通常你想避免这样的稀疏列。与 EF6 实现相比,还有一个优势:该模型允许双向导航。 Image可以用 Person 扩展和 Product导航属性。
    EF 在将其转化为数据库设计方面做得非常好。每个外键都有一个过滤的唯一索引,例如 Person :
    CREATE UNIQUE NONCLUSTERED INDEX [IX_Image_PersonID] ON [dbo].[Image]
    (
    [PersonID] ASC
    )
    WHERE ([PersonID] IS NOT NULL)
    这将关联变成了数据库端真正的 1:1 关联。如果没有唯一索引,从数据库的角度来看,它将是 1:n 关联。

    关于c# - 使用实体配置与多个表的一对一/一关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50582377/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com