【问题标题】:One-to-one relationship in EFEF中的一对一关系
【发布时间】:2015-01-28 18:41:04
【问题描述】:

我的模型如下所示:

public class Job
{
    public int Id { get; set; }
    public virtual JobResult Result { get; set; }
}
public class JobResult
{
    [Key, ForeignKey("Job")]
    public int JobId { get; set; }
    [Required]
    public virtual Job Job { get; set; }
}

如您所见,这种关系是必需的一对一关系。 当我尝试创建和保存作业时:

Job job = new Job();
job.Result = new Result();
context.Jobs.add(job);
context.SaveChanges();

我收到以下错误:

无法确定相关操作的有效顺序。 由于外键约束,模型可能存在依赖关系 需求或存储生成的值。

我不太明白错误信息。这是什么意思,什么可能导致这个错误?

【问题讨论】:

  • How do I create a real one-to-one relationship in SQL Server 的可能副本。我很确定在 SQL Server 中建立真正的 1 对 1 关系在技术上是不可能的,因为这意味着你必须同时插入两条记录(否则你会在插入时遇到约束错误),在两个表,两个表之间具有外键关系。
  • @ErikPhilips - 他在下面的评论中提到实际上是 1:0..1 而不是 1:1,因为 JobResult 是可选的
  • @ErikFunkenbusch 问题应该已经更新,因为所有问题都应该是自给自足的,不需要任何人阅读 cmets 或 cmets 的答案。
  • @ErikPhilips - 我同意,只是指出来......

标签: database entity-framework entity-framework-6


【解决方案1】:

您的案例无效,因为这是一个循环引用。必须做什么 EF:

  1. 插入JobResults(....., Job_Id)(....., @JobId);

EF 不能这样做,因为 Job 没有插入并且没有 Id。

  1. 插入Jobs(....., JobResult_Id)(....., @JobResultId);

EF 也不能这样做,因为 JobResult 没有插入并且没有 ID。 这是一个恶性循环。

您可以修改您的模型。摆脱其中一个链接。示例:

public class Job
{
    public int Id { get; set; }
    public virtual JobResult Result { get; set; }
}

public class JobResult
{
    public int Id { get; set; }
    public virtual Job Job { get; set; }
}

class JobResultConfiguration : EntityTypeConfiguration<JobResult>
{
    public JobResultConfiguration()
    {
        HasRequired(e => e.Job).WithRequiredPrincipal(e => e.Result); // one-to-one
    }
}

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new JobResultConfiguration());
    }
}

这将允许您这样做:

Job job = new Job();
job.Result = new Result();
context.Jobs.add(job);
context.SaveChanges();

EF 建立一对一关系:两个实体与两个具有相同主键的实体。

更多关于 Fluent Api 的详细信息:https://msdn.microsoft.com/en-us/data/jj591620.aspx

或者你的地方修改了模型域。当你循环链接时,我会尝试摆脱一个链接(或来自 Job 或来自 JobResult)

【讨论】:

  • 我明白了。你会建议我做什么来解决这个问题?另外,为什么 EF 不能将 Job 插入数据库? JobResult 是可选的,所以不能在 JobResultId 中插入 0 吗?
  • 我明白了。但是,我更愿意将我的操作保留为单个事务。真的没有办法做到这一点吗?
  • 我在上面更新了我的答案。如果您可以放弃一个参考,那么最后一个选项就是您所需要的。
  • 删除其中一个引用似乎是最好的选择(尽管不是我所希望的)。如果没有一个字段被标记为 [Required],我是否仍然无法将它们插入到单个事务中?我的意思是一对一的关系一定很普遍吧?
  • 是的,您仍然无法执行此交易。您可以在纯 SQL 上执行此事务。设计域模型时是一个很好的做法 - 尽量减少实体中的链接数量。这将简化映射以及逻辑域。
【解决方案2】:

您的 [Required] 字段位于您正在执行的操作类型的错误元素上。因为您需要JobResult 才能拥有Job,所以您可以创建JobResult,然后创建从属Job(没有要求),但反之则不行。如果您尝试从Job 端创建它,则Job 在创建之前不会附加到JobResult,但在JobResult 创建循环引用之前无法创建它。

【讨论】:

  • 我尝试从 JobResult.Job 中删除 [Required] - 但是现在我收到此错误消息:“无法确定相关操作的有效排序。由于外键约束,模型可能存在依赖关系需求或存储生成的值。”
  • 您可能需要使用fluentApi来配置操作顺序。见stackoverflow.com/questions/26389707/…
  • 我已经查看了线程,但我不太明白 FluentAPI 如何在我的案例中作为解决方案应用。你介意给我举个例子吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 2021-07-21
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
  • 1970-01-01
  • 2019-07-25
相关资源
最近更新 更多