如何在EntityFramework中配置此关系(1->很多,再加上1-> 0或1,没有连接表)

时间:2019-01-26 19:46:00

标签: c# entity-framework

我知道一个现实的选择是更改建议的数据库模式。我也在追求这种选择。但是...我想知道是否可以设置EF,以便它可以理解这种结构....


商业模式:

  • 每个Foo都与酒吧相关联。
  • 每个Bar可以有多个Foos。
  • 每个Bar也可能有一个 special Foo,(尽管可能没有一个)

加强“酒吧的特殊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是正确的,而且我不知道如何配置它。

有人知道怎么做吗?

1 个答案:

答案 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。