从1到0,一种关系

本文关键字:一种 关系 | 更新日期: 2023-09-27 18:08:31

我似乎弄不清楚FooBar之间的关系。

public class Foo
{
    [Key]
    public int Id { get; set; }
    public int Name { get; set; }
    public virtual Bar Bar { get; set; }
}

public class Bar
{
    [Key]
    public int Id { get; set; }
    public int Name { get; set; }
    public int FooId { get; set; }
    public virtual Foo Foo { get; set; }
}

在这种结构下,我通常会写

public virtual ICollection<Bar> Bars { get; set; }

,但在这个例子中,这不是我的数据的一个可行的表示。

你看…

Foo并不总是有Bar…但是…Bar总是有一个Foo并且它的FooId在Bar中总是唯一的。

public class MyContext : DbContext
{
    public DbSet<Foo> Foos { get; set; }
    public DbSet<Bar> Bars { get; set; }
    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        // ...............
        modelBuilder.Entity<Foo>()
                    .HasOptional(cpi => cpi.Bar)
                    .WithRequired(api => api.Foo);
        // ...............
    }
}

我已经多次尝试定义这种关系,但似乎不能得到它的权利!我还可以向Foo添加一个可空的BarId,如果这样可以让我做我想做的事情(但我不希望这样做)。(见编辑1)

我在谷歌上搜索了很多(并且搜索了,并且尝试了),许多堆栈溢出的帖子都是类似的(但不相同)。

如有任何意见,不胜感激。

感谢

编辑1(回应消费者评论):

这些表已经存在于许多生活环境中,并且充满了数据,所以我想找到一个不编辑db表定义的解决方案…但如果这是不可能的,我可以添加一个列来实现我需要的。

之前我把它定义为…

public virtual ICollection<Bar> Bars { get; set; }

…但是对于我正在使用这些表编写的一段代码,这将不起作用。


编辑2:

当我尝试添加一个Bar时,上面的代码给出了以下错误:

"当IDENTITY_INSERT设置为OFF时,无法在表'Bar'中插入标识列的显式值。"

标识插入没有关闭,我对所有表都使用它,除了在这种情况下,EF似乎根据我对这些表的定义关闭了它。

从1到0,一种关系

我们可以试试DataAnnotations吗?

public class Foo
{
    public int Id { get; set; }
    public string  Name { get; set; }
    public virtual Bar Bar { get; set; }
}

public class Bar
{
    [Key, ForeignKey("Foo")]
    public override int Id {get;set;}
    public string Name { get; set; }
    public virtual Foo Foo { get; set; }
}

所以你真正的问题是

当IDENTITY_INSERT设置为OFF时,无法在表'Bar'中插入标识列的显式值

首先,此错误消息意味着:您正在尝试将值插入标识列,而当前配置为不允许该操作(off)

实体框架可能试图插入零,因为你没有告诉EF关于身份列;这意味着您需要显式地告诉EF,您的this列正在从数据库生成您的id…

protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<Foo>()
                .HasOptional(cpi => cpi.Bar)
                .WithRequired(api => api.Foo);
    // needed
    modelBuilder.Entity<Bar>()
      .HasKey(b => b.Id)
      .Property(b => b.Id)
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}

对象是可空的,所以关系是可选的,不需要您做任何与.HasOptional()声明不同的事情。

但是,您丢失了关系中的外键。

public class Foo
{
    [Key]
    public int Id { get; set; }
    public int Name { get; set; }
    public int BarId { get; set; } // Add this!
    [ForeignKey(nameof(BarId))] // Add this!
    public virtual Bar Bar { get; set; }
}
public class Bar
{
    [Key]
    public int Id { get; set; }
    public int Name { get; set; }
    public int FooId { get; set; }
    [ForeignKey(nameof(FooId))] // Add this!
    public virtual Foo Foo { get; set; }
}