我正在为这两个表开发一个包含Entity Framework 6.1.2的库:
CREATE TABLE [dbo].[CODES]
(
[CODE] [nvarchar](20) NOT NULL,
[ ... ],
CONSTRAINT [PK_CODES] PRIMARY KEY CLUSTERED
(
[CODE] ASC
)
)
CREATE TABLE [dbo].[AGGREGATIONS]
(
[ID_AGGREGATION] INT IDENTITY(1,1) NOT NULL,
[CODE_LEVEL] TINYINT NOT NULL,
[CODE] NVARCHAR(20) NOT NULL,
[ ... ],
CONSTRAINT [PK_AGGREGATIONS] PRIMARY KEY CLUSTERED
(
[ID_AGGREGATION] ASC
),
CONSTRAINT [FK_AGGREGATIONS_CODES] FOREIGN KEY ([CODE]) REFERENCES [dbo].[CODES] ([CODE])
)
关系:
我CODES
可能只有一个AGGREGATIONS
,但AGGREGATIONS
会有一个CODES
。
要做到这一点,我有这两个实体类:
public class CODES
{
public string CODE { get; set; }
[ ... ]
public virtual AGGREGATIONS Aggregation { get; set; }
public virtual AGGREGATION_CHILDS AggregationChild { get; set; }
}
public class AGGREGATIONS
{
public int ID_AGGREGATION { get; set; }
public string CODE { get; set; }
public byte CODE_LEVEL { get; set; }
public virtual CODES Code { get; set; }
}
我试过这个来设置AGGREGATIONS
和CODES
之间关于聚合的关系&#39; EntityTypeConfiguration<AGGREGATIONS>
:
HasKey(ag => ag.ID_AGGREGATION);
HasRequired(ag => ag.Code).WithOptional(c => c.Aggregation);
但我不知道如何将AGGREGATIONS.CODE
设置为此关系中的外键。
如何在这种关系上设置FK?
更新
我需要使用AGGREGATIONS.ID_AGGREGATION
,因为还有另一个表具有AGGREGATIONS
和CODES
表的外键:
CREATE TABLE [dbo].[AGGREGATION_CHILDS]
(
[ID_AGGREGATION] [int] NOT NULL,
[CODE] [nvarchar](20) NOT NULL,
[CODE_LEVEL] [tinyint] NOT NULL,
[POSITION] [int] NOT NULL,
CONSTRAINT [PK_AGGREGATION_CHILDS] PRIMARY KEY CLUSTERED
(
[ID_AGGREGATION] ASC,
[CODE] ASC
),
CONSTRAINT [FK_AGGREGATION_CHILDS_AGGREGATIONS] FOREIGN KEY ([ID_AGGREGATION]) REFERENCES [AGGREGATIONS]([ID_AGGREGATION]),
CONSTRAINT [FK_AGGREGATION_CHILDS_CODES] FOREIGN KEY ([CODE]) REFERENCES [CODES]([CODE])
如果我在answer中按照您的建议行事,我会在CODE
表格中有两列AGGREGATION_CHILDS
。其中一个将是AGGREGATIONS
表的外键,也是CODES
表的外键。而另一个FK到CODES
表。
答案 0 :(得分:2)
在一对一关系中,EF要求依赖实体的密钥也必须是委托人的外键,因此,您的模型将如下所示:
public class CODES
{
[Key]
public string CODE { get; set; }
[ ... ]
public virtual AGGREGATIONS Aggregation { get; set; }
}
public class AGGREGATIONS
{
[Key, ForeignKey("Codes")]
public string CODE { get; set; }
public byte CODE_LEVEL { get; set; }
public virtual CODES Code { get; set; }
}
如果您需要使用Fluent Api,我认为您可以在Aggregations
的配置类中执行此操作:
HasKey(ag=>ag.Code);
HasRequired(ag => ag.Code).WithOptional(c => c.Aggregation);
您可以在此page找到更多信息。
为了达到你想要的效果,由于我在上面评论的限制,你不能在依赖实体中声明FK属性。所以你的模型会是这样的:
public class CODES
{
[Key]
public string CODE { get; set; }
[Required]
public virtual AGGREGATIONS Aggregation { get; set; }
public ICollection<AGGREGATION_CHILDS> AggregationChilds { get; set; }
}
public class AGGREGATIONS
{
[Key]
public int ID_AGGREGATION { get; set; }
public byte CODE_LEVEL { get; set; }
public virtual CODES Code { get; set; }
public ICollection<AGGREGATION_CHILDS> AggregationChilds { get; set; }
}
public class AGGREGATION_CHILDS
{
[Key,Column(Order = 0),ForeignKey("Code")]
public string CODE { get; set; }
[Key,Column(Order = 1),ForeignKey("Aggregation")]
public int ID_AGGREGATION { get; set; }
public virtual CODES Code { get; set; }
public virtual AGGREGATIONS Aggregation { get; set; }
}
如果您不想使用数据注释,可以删除所有属性并使用配置类中的Fluent Api指定相同的属性:
public class CodesMap : EntityTypeConfiguration<CODES>
{
public CodesMap()
{
// Primary Key
this.HasKey(t => t.CODE);
}
}
public class AggregationsMap : EntityTypeConfiguration<AGGREGATIONS>
{
public AggregationsMap()
{
// Primary Key
this.HasKey(t => t.ID_AGGREGATION);
HasRequired(ag => ag.Code).WithOptional(c => c.Aggregation);
}
}
public class AggregationChildsMap : EntityTypeConfiguration<AGGREGATIONS_CHILDS>
{
public AggregationChildsMap()
{
// Primary Key
this.HasKey(t => new{t.CODE,t.ID_AGGREGATION});
HasRequired(t => t.Code).WitMany(c => c.AggregationChilds).HasForeignKey(t=>t.CODE);
HasRequired(t => t.Aggregation).WitMany(ag => ag.AggregationChilds).HasForeignKey(t=>t.ID_AGGREGATION);
}
}
无法在AGGREGATION_CHILDS
中指定复合PK并在此实体与AGGREGATIONS
之间配置一对一关系,除非复合键也是AGGREGATIONS
中的键。 。如果要创建一对一关系并在dependend实体中指定FK属性,那么该FK也必须是PK,因此两个实体必须共享相同的PK。如果在该dependend实体中声明另一个Key,其中FK与另一个关系相关,那么EF会期望这两个关系应该是一对多的(就像我在Update 1中显示的那样)。如果您尝试创建两个一对一关系,并尝试将从属端的PK与主体的PK复合,那么您将收到此异常:
AGGREGATION_CHILDS_Aggregation_Source ::多重性无效 关系中的角色'AGGREGATION_CHILDS_Aggregation_Source' 'AGGREGATION_CHILDS_Aggregation'。因为依赖角色 属性不是关键属性,是上限 依赖角色的多样性必须为'*'。
AGGREGATION_CHILDS_Code_Source ::多重性在角色中无效 'AGGREGATION_CHILDS_Code_Source'的关系 'AGGREGATION_CHILDS_Code'。因为依赖角色属性是 不是关键属性,多重性的上限 依赖角色必须是'*'。
答案 1 :(得分:0)
我认为你几乎就在那里。对于可选的Codes.Aggregation
尝试:
HasRequired(ag => ag.Code).WithOptional(c => c.Aggregation);
或在您的上下文类中:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Aggregations>()
.HasRequired(a => a.Code)
.WithOptional(c => c.Aggregation);
}
答案 2 :(得分:0)
这就是我解决问题的方法:
public class CODES
{
public string CODE { get; set; }
public byte CODE_LEVEL { get; set; }
[ ... ]
public virtual AGGREGATION_CHILDS AggregationChild { get; set; }
public virtual AGGREGATIONS Aggregation { get; set; }
}
public class AGGREGATIONS
{
public string CODE { get; set; }
public string CREATED { get; set; }
public virtual ICollection<AGGREGATION_CHILDS> AggregationChilds { get; set; }
public virtual CODES Code { get; set; }
}
public class AGGREGATION_CHILDS
{
public string CODE { get; set; }
public string PARENT_CODE { get; set; }
public int POSITION { get; set; }
public AGGREGATIONS Aggregation { get; set; }
public CODES Code { get; set; }
}
他们的地图:
class AGGREGATIONSConfiguration : EntityTypeConfiguration<AGGREGATIONS>
{
public AGGREGATIONSConfiguration()
{
HasKey(ag => ag.CODE);
Property(ag => ag.CODE)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
Property(ag => ag.CODE)
.HasMaxLength(20)
.IsRequired();
Property(ag => ag.CREATED)
.HasMaxLength(50)
.IsOptional();
HasRequired(ag => ag.Code)
.WithOptional(c => c.Aggregation)
.WillCascadeOnDelete(false);
}
}
class AGGREGATION_CHILDSConfiguration : EntityTypeConfiguration<AGGREGATION_CHILDS>
{
public AGGREGATION_CHILDSConfiguration()
{
HasKey(ag_ch => ag_ch.CODE);
Property(ag_ch => ag_ch.CODE)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
Property(ag_ch => ag_ch.CODE)
.HasMaxLength(20)
.IsRequired();
Property(ag_ch => ag_ch.PARENT_CODE)
.HasMaxLength(20)
.IsRequired();
HasRequired(ag_ch => ag_ch.Aggregation)
.WithMany(ag => ag.AggregationChilds)
.HasForeignKey(ag_ch => ag_ch.PARENT_CODE);
HasRequired(ag_ch => ag_ch.Code)
.WithOptional(c => c.AggregationChild)
.WillCascadeOnDelete(false);
}
}
CODESConfiguration
与此无关。
我在CODE
和AGGREGATIONS
以及 FK 上使用AGGREGATION_CHILDS
作为 PK 到CODES
表。
我已从ID_AGGREGATION
表格移除AGGREGATIONS
,并在AGGREGATION_CHILDS
表格中移除了复合 PK 。
我希望它可以帮助那些在“一对一”或“一对一”关系中遇到同样问题的人。