一对零......一个关系

时间:2016-09-22 15:13:13

标签: c# entity-framework ef-model-builder

我似乎无法正确理解 Foo Bar 之间的关系。

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中

,但在这种情况下,这不是我数据的可行表示。

你看......

Foo 并不总是有 Bar ...但... Bar 将始终具有 Foo ,并且其 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似乎根据我对这些表的定义将其关闭。

3 个答案:

答案 0 :(得分:0)

所以你真正的问题是

  

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

首先,此错误消息表示:您正在尝试将值插入标识列,当前配置为不允许该操作(关闭)

实体框架可能会尝试插入零,因为您没有告诉EF关于身份列;这意味着您需要明确告诉EF您的此列正在从数据库中生成您的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);
}

答案 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; }
}

答案 2 :(得分:0)

对象可以为空,因此可选的关系不需要您执行与.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; }
}