我知道一个现实的选择是更改建议的数据库模式。我也在追求这种选择。但是...我想知道是否可以设置EF,以便它可以理解这种结构....
商业模式:
加强“酒吧的特殊Foo必须与该酒吧相关联”的一致性是代码库而不是数据库的责任。
加强一致性“一个酒吧最多只能有一个特殊的Foo”是数据库的责任。
选择的数据库模型:
如上所述,我知道存在其他可能的结构,它们具有许多优点(尤其是“在EF中更易于配置”)。
CREATE TABLE [dbo].[Foo] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[BarId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_Bar] FOREIGN KEY ([BarId]) REFERENCES [dbo].[Bar] ([Id])
);
CREATE TABLE [dbo].[Bar] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[SpecialFooId] INT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_SpecialFoo] FOREIGN KEY ([SpecialFooId]) REFERENCES [dbo].[Foo] ([Id])
);
当前对领域模型的猜测:
public class Foo
{
public int Id { get; set; }
// Props for easy 1-many relationship.
public int BarId { get; set; }
public virtual Bar Bar { get; set; }
}
public class Bar
{
public int Id { get; set; }
// Prop for easy 1-many relationship.
public virtual ICollection<Foo> Foos { get; set; }
// Props for hard 1-0..1 relationship.
public int? SpecialFooId { get; set; }
public virtual Foo SpecialFoo { get; set; }
}
我完全不确定该域对象模型对于EF是正确的,而且我不知道如何配置它。
有人知道怎么做吗?
答案 0 :(得分:0)
根本上,我无法进行这项工作的原因是上述的DB模型并没有反映在上述的C#域对象模型中。
基于该数据库模型,单个Foo可能是多个 Bars的SpecialFoo-从Bar到Foo的FK不知道业务逻辑将确保实际上最多有一个指向任何给定Foo的那些FK中的一个。
因此,类模型必须为:
public class Foo
{
public int Id { get; set; }
// Props for easy 1-many relationship.
public int BarId { get; set; }
public virtual Bar Bar { get; set; }
//****** THE CHANGED BIT ******
public ICollection<Bar> BarsForWhichThisIsTheSpecialFoo { get; set; }
//****** THE CHANGED BIT ******
}
public class Bar
{
public int Id { get; set; }
// Prop for easy 1-many relationship.
public virtual ICollection<Foo> Foos { get; set; }
// Props for hard 1-0..1 relationship.
public int? SpecialFooId { get; set; }
public virtual Foo SpecialFoo { get; set; }
}
然后正确的Modelbuilder咒语是:
modelBuilder.Entity<Bar>()
.HasMany(bar => bar.Foos)
.WithRequired(foo => foo.Bar)
.HasForeignKey(foo => foo.BarId);
modelBuilder.Entity<Foo>()
.HasMany(foo => foo.BarsForWhichThisIsTheSpecialFoo)
.WithOptional(bar => bar.SpecialFoo)
.HasForeignKey(bar => bar.SpecialFooId);
表示更改后的p.o.v。关系的依据:根据数据库,酒吧实际上并没有自己的SpecialFoo ... Foos有一系列他们特别的Bars。