从1到0,一种关系
本文关键字:一种 关系 | 更新日期: 2023-09-27 18:08:31
我似乎弄不清楚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并不总是有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似乎根据我对这些表的定义关闭了它。
我们可以试试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; }
}