[英]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
属性类型为decimal
而GroupMetier.GroupId
属性类型为int
,在这种情况下,EF无法识别该关系,并尝试使用当然不匹配的一对一外键关联您的数据库模型。
How to fix it? 如何解决? It's hard to tell, but you somehow should make both properties int
or decimal
. 很难说,但是您应该以某种方式使这两个属性都为int
或decimal
。
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.