简体   繁体   English

实体框架中的一对零或一种关系

[英]one to zero or one relationship in entity framework

I have 2 standard entities : 我有2个标准实体:

Group : 组别:

[Table("CONTROL_GROUP", Schema = "CONTROL")]
public partial class Group
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Required]
    [Column("ID")]
    public decimal Id { get; set; }

    [Required]
    [Column("NAME")]
    [MaxLength(200)]
    public string Name { get; set; }

    public virtual GroupMetier GroupMetier { get; set; }
}

GroupMetier: GroupMetier:

[Table("CONTROL_GROUP_METIER", Schema = "CONTROL")]
public partial class GroupMetier
{
    [Key]
    [Required]
    [Column("GROUP_ID")]
    public int GroupId { get; set; }

    [Required]
    [Column("NAME")]
    [MaxLength(200)]
    public string Name { get; set; }

    public virtual Group Group { get; set; }
}

In my model builder, I defined the relashionship as follow : 在我的模型构建器中,我定义了以下关系:

// GroupMetier 0..1 <-> 1 Group
modelBuilder.Entity<GroupMetier>()
    .HasRequired<Group>(gm => gm.Group)
    .WithOptional(g => g.GroupMetier)

However, on execution, when I try to retrive the groups with this linq : 但是,在执行时,当我尝试使用此linq检索组时:

_context.Groups.Where(item => item.GroupMetier != null)

The generated sql failed to execute : 生成的sql执行失败:

SELECT 
    "Extent3"."GROUP_ID" AS "GROUP_ID", 
    "Extent1"."ID" AS "ID", 
    "Extent1"."NAME" AS "NAME", 
    "Extent2"."GROUP_ID" AS "GROUP_ID1"
FROM   "CONTROL"."CONTROL_GROUP" "Extent1"
    LEFT OUTER JOIN "CONTROL"."CONTROL_GROUP_METIER" "Extent2" ON "Extent1"."ID" = "Extent2"."GroupId"
    INNER JOIN "CONTROL"."CONTROL_GROUP_METIER" "Extent3" ON "Extent1"."ID" = "Extent3"."GroupId"
WHERE (1 = 1)

The problem come obviously from entity trying to join on an non existing "Extent2"."GroupId" column instead of the right "Extent2"."GROUP_ID" 问题显然来自实体试图加入不存在的"Extent2"."GroupId"列而不是右"Extent2"."GROUP_ID"

Have I failed to declare something somewhere for this relashionship to work ? 我是否未能在某处声明某些内容以使这种冲突有效?

Edit : As requested, the CONTROL.CONTROL_GROUP_METIER table : 编辑:根据要求,CONTROL.CONTROL_GROUP_METIER表:

CREATE TABLE CONTROL.CONTROL_GROUP_METIER
(
  GROUP_ID  INTEGER                             NOT NULL,
  NAME      VARCHAR2(200 CHAR)                  NOT NULL
)
TABLESPACE CONTROL_DATA
RESULT_CACHE (MODE DEFAULT)
PCTUSED    0
PCTFREE    10
INITRANS   1
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            NEXT             1M
            MAXSIZE          UNLIMITED
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
            FLASH_CACHE      DEFAULT
            CELL_FLASH_CACHE DEFAULT
           )
LOGGING 
NOCOMPRESS 
NOCACHE
NOPARALLEL
MONITORING;


CREATE UNIQUE INDEX CONTROL.CONTROL_GROUP_METIER_PK ON CONTROL.CONTROL_GROUP_METIER
(GROUP_ID)
LOGGING
TABLESPACE CONTROL_DATA
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            NEXT             1M
            MAXSIZE          UNLIMITED
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
            FLASH_CACHE      DEFAULT
            CELL_FLASH_CACHE DEFAULT
           )
NOPARALLEL;


ALTER TABLE CONTROL.CONTROL_GROUP_METIER ADD (
  CONSTRAINT CONTROL_GROUP_METIER_PK
  PRIMARY KEY
  (GROUP_ID)
  USING INDEX CONTROL.CONTROL_GROUP_METIER_PK
  ENABLE VALIDATE);

ALTER TABLE CONTROL.CONTROL_GROUP_METIER ADD (
  CONSTRAINT CONTROL_GROUP_METIER_R01 
  FOREIGN KEY (GROUP_ID) 
  REFERENCES CONTROL.CONTROL_GROUP (ID)
  ENABLE VALIDATE);

Have I failed to declare something somewhere for this relashionship to work ? 我是否未能在某处声明某些内容以使这种冲突有效?

Your configuration is just fine for so called Shared Primary Key Association and normally would produce a migration like this (just to test the mapping): 您的配置对于所谓的“ 共享主键关联”来说很好,并且通常会产生这样的迁移(仅用于测试映射):

CreateTable(
    "CONTROL.CONTROL_GROUP_METIER",
    c => new
        {
            GROUP_ID = c.Int(nullable: false),
            NAME = c.String(nullable: false, maxLength: 200),
        })
    .PrimaryKey(t => t.GROUP_ID)
    .ForeignKey("CONTROL.CONTROL_GROUP", t => t.GROUP_ID)
    .Index(t => t.GROUP_ID);

However, it actually produces this: 但是,它实际上会产生以下结果:

CreateTable(
    "CONTROL.CONTROL_GROUP_METIER",
    c => new
        {
            GROUP_ID = c.Int(nullable: false, identity: true),
            NAME = c.String(nullable: false, maxLength: 200),
            Group_Id = c.Decimal(nullable: false, precision: 18, scale: 2),
        })
    .PrimaryKey(t => t.GROUP_ID)
    .ForeignKey("CONTROL.CONTROL_GROUP", t => t.Group_Id)
    .Index(t => t.Group_Id);

which as you can see is not what you want. 如您所见,这不是您想要的。

Why is that? 这是为什么? To better understand, let apply the explicit ForeignKey attribute to the Group property: 为了更好地理解,请将显式的ForeignKey属性应用于Group属性:

[ForeignKey("GroupId")]
public virtual Group Group { get; set; }

Now the migration fails with the following error: 现在,迁移失败,并显示以下错误:

GroupMetier_Group_Target_GroupMetier_Group_Source: : The types of all properties in the Dependent Role of a referential constraint must be the same as the corresponding property types in the Principal Role. GroupMetier_Group_Target_GroupMetier_Group_Source::引用约束的“从属角色”中所有属性的类型必须与“主体角色”中相应的属性类型相同。 The type of property 'GroupId' on entity 'GroupMetier' does not match the type of property 'Id' on entity 'Group' in the referential constraint 'GroupMetier_Group'. 实体“ GroupMetier”上的属性“ GroupId”的类型与引用约束“ GroupMetier_Group”中实体“ Group”的属性“ Id”的类型不匹配。

So the problem is that the Group.Id property type is decimal and GroupMetier.GroupId property type is int , in which case EF fails to recognize the relationship and tries to use One-to-One Foreign Key Association which of course doesn't match your database model. 因此,问题在于Group.Id属性类型为decimalGroupMetier.GroupId属性类型为int ,在这种情况下,EF无法识别该关系,并尝试使用当然不匹配的一对一外键关联您的数据库模型。

How to fix it? 如何解决? It's hard to tell, but you somehow should make both properties int or decimal . 很难说,但是您应该以某种方式使这两个属性都为intdecimal

Did you try the ForeignKey annotation? 您是否尝试了ForeignKey注释?

[ForeignKey("GROUP_ID")]
public virtual Group Group { get; set; }

in fluent API 在流利的API中

modelBuilder.Entity<GroupMetier>()
.HasRequired<Group>(gm => gm.Group)
.WithOptional(g => g.GroupMetier)
.Map(g => g.MapKey("GROUP_ID"));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM