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

时间:2017-01-06 09:26:18

标签: c# oracle entity-framework linq entity-framework-6

我有2个标准实体:

组:

[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:

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

在我的模型构建器中,我将关系定义如下:

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

但是,在执行时,当我尝试使用此linq来检索组时:

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

生成的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)

问题显然来自于尝试加入非现有"Extent2"."GroupId"列而非右"Extent2"."GROUP_ID"

的实体

我是否未能在某个地方宣布这种关系起作用?

编辑:根据要求,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);

3 个答案:

答案 0 :(得分:2)

  

我是否未能在某个地方宣布这种关系起作用?

您的配置适用于所谓的Shared Primary Key Association,通常会产生这样的迁移(只是为了测试映射):

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

然而,它实际上产生了这个:

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

你可以看到的并不是你想要的。

为什么?为了更好地理解,请将显式ForeignKey属性应用于Group属性:

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

现在迁移失败并出现以下错误:

  

GroupMetier_Group_Target_GroupMetier_Group_Source ::参照约束的从属角色中的所有属性的类型必须与“主体角色”中的相应属性类型相同。财产的类型&#39; GroupId&#39;实体&#39; GroupMetier&#39;不符合财产的类型&#39; Id&#39;实体&#39; Group&#39;在参考约束&#39; GroupMetier_Group&#39;。

所以问题是Group.Id属性类型是decimalGroupMetier.GroupId属性类型是int,在这种情况下,EF无法识别关系并尝试使用One-to-One Foreign Key Association这当然与您的数据库模型不匹配。

如何解决?这很难说,但你不知何故应该同时制作intdecimal两个属性。

答案 1 :(得分:1)

您是否尝试过ForeignKey注释?

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

答案 2 :(得分:0)

在流畅的API中

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