【问题标题】:Entity Framework 6 inserts null as primary key while inserting nested identifying relationshipsEntity Framework 6 在插入嵌套标识关系时插入 null 作为主键
【发布时间】:2016-10-12 00:16:31
【问题描述】:

我使用 EF6 Code First 定义了四个实体:

public class Item1
{
    [Key]
    [StringLength(50)]
    public string Name { get; set; }
}

public partial class Item2
{
    [Key]
    [Column(Order = 0)]
    [StringLength(50)]
    public string Item1Name { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(50)]
    public string Name { get; set; }
}

public partial class Item3
{
    [Key]
    [Column(Order = 0)]
    [StringLength(50)]
    public string Item1Name { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(50)]
    public string Item2Name{ get; set; }

    [Key]
    [Column(Order = 2)]
    [StringLength(50)]
    public string Name { get; set; }
}

public partial class Item4
{
    [Key]
    [Column(Order = 0)]
    [StringLength(50)]
    public string Item1Name { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(50)]
    public string Item2Name{ get; set; }

    [Key]
    [Column(Order = 2)]
    [StringLength(50)]
    public string Item3Name{ get; set; }

    [Key]
    [Column(Order = 3)]
    [StringLength(50)]
    public string Name{ get; set; }
}

(我省略了导航属性,但它们在那里。)

这样定义的关系:

modelBuilder.Entity<Item1>()
            .HasMany(e => e.Item2s)
            .WithRequired(e => e.Item1)
            .HasForeignKey(e => new { e.Item1Name})
            .WillCascadeOnDelete(false);

modelBuilder.Entity<Item2>()
            .HasMany(e => e.Item3s)
            .WithRequired(e => e.Item2)
            .HasForeignKey(e => new { e.Item1Name, e.Item2Name })
            .WillCascadeOnDelete(false);

modelBuilder.Entity<Item3>()
            .HasMany(e => e.Item4s)
            .WithRequired(e => e.Item3)
            .HasForeignKey(e => new { e.Item1Name, e.Item2Name, e.Name})
            .WillCascadeOnDelete(false);

现在,当我尝试像这样将 Item3 插入到 existingItem2.Item3s 中时:

Item3 newItem3 = new Item3();
newItem3.Item4s.Add(new Item4());
existingItem2.Item3s.Add(newItem3);
db.SaveChanges();

我收到以下错误:

无法将值 NULL 插入到列“Item1Name”、表“Database.dbo.Item4s”中;列不允许空值。 INSERT 失败。\r\n语句已终止。

奇怪的是,在没有嵌套 Item4 的情况下将 Item3 插入到 existingItem2.Item3s 中后,我可以使用上述过程插入嵌套项目而不会出现任何错误。我试过用[DatabaseGenerated(DatabaseGeneratedOption.None)] 明确指定所有键,但这没有区别。这里有什么可以玩的?

编辑

我缩小了错误的范围,以及为什么它有时会发生有时不会发生。在我的程序中,除了我所描述的之外,我还设置了existingItem2.someUnrelatedNonKeyIntegerValue = someValue;。事实证明,如果这实际上会改变值(它总是被设置),EF 将生成一个失败的查询。似乎是EF中的一个错误,对吗?我是这样解决它的:

if (existingItem2.someUnrelatedNonKeyIntegerValue != someValue)
{
   existingItem2.someUnrelatedNonKeyIntegerValue = someValue;
   db.SaveChanges();
}
Item3 newItem3 = new Item3();
newItem3.Item4s.Add(new Item4());
existingItem2.Item3s.Add(newItem3);
db.SaveChanges();

(顺便说一下,整数名称中不包含ID,并且确实没有标记为数据库中的键。)

【问题讨论】:

  • 您是否需要按原样使用数据模型?它的设计真的很糟糕,这可能是你的一些痛苦的原因。每个表都应该有一个代理键,它成为层次结构中下一个表的外键。从长远来看,修复数据库的设计可能会解决您的问题并为您提供更好的结构。
  • 我同意 Craig W 的观点。这个简单的模型已经给你带来了问题。我们甚至没有谈论性能。我怀疑这是 EF 中的一个错误,更有可能它不是为那样使用而设计的。出于最好的考虑,我建议您下载 EF6 教程并花一些时间从中学习,而不是寻找解决方法。这是一个:asp.net/mvc/overview/getting-started/… 请注意,键是 int 类型和名称 Id 的单个属性。
  • @RuardvanElburg 谢谢,但我已经很熟悉了。事实上,在我将其重构为当前设计之前,我就是这样做的。识别数据库设计中的关系不是我自己提出的结构,EF 以多种方式支持它。例如,如果与父级的关系正在识别 (stackoverflow.com/a/17726414/6452047),则 DBSet.Remove() 会自动删除实体。
  • @CraigW。不是必需的,但这很有意义,因为我主要根据用户通过 Web API 调用发送的父 item1 和 item2 的名称进行大量查询来检索 Item3 对象。

标签: c# .net sql-server entity-framework entity-framework-6


【解决方案1】:

对数据库表一无所知...

如果映射到 Item1Name 的列与模型中的属性具有相同的数据类型,您可以通过更改表列以允许空值或在构造函数中初始化模型属性来解决此问题。

public partial class Item3
{
    public Item3()
    {
     Item1Name = string.empty;
     Item2Name = string.empty;
     Name = string.empty;
    }

    [Key]
    [Column(Order = 0)]
    [StringLength(50)]
    public string Item1Name { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(50)]
    public string Item2Name{ get; set; }

    [Key]
    [Column(Order = 2)]
    [StringLength(50)]
    public string Name { get; set; }
}

【讨论】:

  • 感谢您的帮助。数据库表由 EF 自己生成。不幸的是,这不起作用,因为 Item1Name 确实必须设置为相应的 item1 主体(在我的问题中可能不清楚 item1 的存在)。我缩小了错误范围,它在编辑后的问题中。
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 2014-05-29
  • 2018-04-02
  • 2018-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-27
相关资源
最近更新 更多