【发布时间】:2018-05-29 21:42:11
【问题描述】:
我正在尝试设计以下实体关系
- 程序
- 组装
一个程序可以有多个程序集。其中一个组件将是主组件。每个程序集只属于一个程序。
类的建模如下:
public class Program
{
public int Id {get;set;}
public virtual ProgramAssembly MainAssembly {get;set;}
public virtual ICollection<ProgramAssembly> Assemblies {get;set;}
}
public class ProgramAssembly
{
public int Id {get;set;}
public virtual Program Program {get;set;}
public int ProgramId {get;set;}
}
我没有使用 FluentApi 指定任何内容(但是,我没有反对它)。
使用上面的代码,我得到了这个错误:
保存不为其关系公开外键属性的实体时发生错误。 EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参阅 InnerException。
InnerException:无法确定相关操作的有效排序。由于外键约束、模型要求或存储生成的值,可能存在依赖关系。
我尝试将 ProgramAssembly 更改为以下内容
public class ProgramAssembly
{
[ForeignKkey("Program")]
public int Id {get;set;}
public virtual Program Program {get;set;}
}
但是,我得到了这个错误:
ProgramAssembly_Program_Source::多重性在关系“ProgramAssembly_Program”中的角色“ProgramAssembly_Program_Source”中无效。因为从属角色是指关键属性,所以从属角色的多重性的上限必须是'1'。
我还尝试了以下流畅的 API 方法
modelBuilder.Entity<ProgramAssembly>()
.HasRequired(a => a.Program)
.WithMany(p => p.Assemblies);
public class ProgramAssembly
{
public int Id { get; set; }
public virtual Program Program { get; set; }
[ForeignKey("Program")] //same error with or without this attribute
public int ProgramId { get; set; }
}
那么错误是:
保存不为其关系公开外键属性的实体时发生错误。 EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参阅 InnerException。 UpdateException:无法确定相关操作的有效排序。由于外键约束、模型要求或存储生成的值,可能存在依赖关系。
如何在不改变在 Assembly 上添加“IsPrimary”属性的方法的情况下允许这种关系?
我在 SO 上看到了一些类似的问题,但它们要么是关于 EF 核心的,例如 this one,要么是建议的重大逻辑更改,例如 this one,甚至是甚至无法编译的 this one。
【问题讨论】:
-
你的模型能改变多少?我认为将
IsPrimary属性添加到Assembly会比拥有两个关系看起来更好 -
@CamiloTerevinto - 谢谢。我可以对模型做任何我想做的事情,但是这种方法是我想要避免的。原因是我最终可能会将任意数量的程序集设置为主要程序集。另外,您如何看待访问程序的初级程序集?
-
通过这种方式指定关系,您将无法做您想做的事情。为了获得类似的东西,您需要像 Camilo 所说的那样,向 ProgramAssembly 实体添加一个“IsMain”属性,如果您想在 Program 实体本身中获取它,您需要将 MainAssembly 属性更改为“public ProgramAssembly MainAssembly {get { return Assemblies.where(asm => asm.IsMain).FirstOrDefault(); }}
-
那只是
program.Assemblies.Single(x => x.IsMain)(或者您甚至可以将其作为导航属性),但是您必须在保存时验证它是对的。 EF Core 的答案应该使用 Fluent API 几乎相同。我很确定你不能通过 DataAnottations 做到这一点 -
@CamiloTerevinto - 谢谢。我尝试了 EF Core 方法,只是将“HasOne”更改为“HasRequired”,但没有奏效。
标签: c# entity-framework ef-code-first