c# - 具有 1 对 1 关系实体框架的抽象类
问题描述
使用实体框架我一直在尝试创建这种关系。基本上我有 1 个具有Result
. 该Result
对象是抽象的,因为它必须是继承自 的 3 个类之一Result
,即Approved
、Rejected
或Modified
:
我正在尝试使用实体框架创建表结构。最初我打算使用 TPCT(每个具体类型的表)结构,所以不会有表,但如果我想引用,我想Result
将链接保留在表中,所以现在我只尝试 TPT 结构。我发现 TPCT 更干净,但最终如果 TPT 是实现我想要的唯一方法,我可以接受。Action
Result
我为我的模型结构尝试了以下变体:
public class Action
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get; set;}
public int Result_Id {get; set;}
[ForeignKey("Result_Id")]
public virtual Result Result {get; set;}
public string Description {get; set;}
}
public abstract class Result
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get; set;}
[Required]
public int Action_Id {get; set;}
[ForeignKey("Action_Id")]
public virtual Action Action {get; set;}
public string Comment {get; set;}
public class Approved : Result
{
public string Thing {get; set;}
}
public class Rejected : Result
{
public string Stuff {get; set;}
}
public class Modified : Result
{
public string Whatever {get; set;}
}
}
然后我在我的上下文文件中尝试了以下两种策略来实现 TPT:
modelBuilder.Entity<Approved>().ToTable("Approved");
modelBuilder.Entity<Rejected>().ToTable("Rejected");
modelBuilder.Entity<Modified>().ToTable("Modified");
或者对于 TCPT:
modelBuilder.Entity<Approved>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Approved");
});
modelBuilder.Entity<Rejected>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Rejected");
});
modelBuilder.Entity<Modified>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Modified");
});
每次我尝试添加新的迁移时,无论我尝试什么,我都会遇到这个错误:
Unable to determine the principal end of an association between the types 'Result' and 'Action'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
我能够让它工作的一次是,如果我从Action
课堂上删除了这个引用:
public int Result_Id {get; set;}
[ForeignKey("Result_Id")]
public virtual Result Result {get; set;}
但我真的很想把那个引用保留在那里,所以当我进入我的数据库来获取那个Action
对象时,我可以立即判断它是否有Result
关联,而不必遍历所有 3 个结果表来查看是否有参考Action
(这就是为什么我认为我需要 TPT ......)
任何帮助来完成这项工作将不胜感激!
解决方案
经过大量的研究和反复试验,我发现了获得想要的结果所需的东西。它是 TPCT DB 结构,并且Action
对象能够保留对Result
. 以下是模型类:
public class Action
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get; set;}
public virtual Result Result {get; set;} //just virtual here, as Action is the dependent and Result is the principal-- i.e. this Result isn't required
public string Description {get; set;}
}
public abstract class Result
{
//got rid of the Result_Id, since it's 1:1 the Action_Id can be the Key
[Required, Key] //added "Key"
public int Action_Id {get; set;}
[ForeignKey("Action_Id")]
public Action Action {get; set;} //removed this virtual, as Action is Required for Result, that makes Result the principal
public string Comment {get; set;}
public class Approved : Result
{
public string Thing {get; set;}
}
public class Rejected : Result
{
public string Stuff {get; set;}
}
public class Modified : Result
{
public string Whatever {get; set;}
}
}
这是上下文中的流畅 API 代码:
//this gave me TPCT like I wanted
modelBuilder.Entity<Approved>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Approved");
});
modelBuilder.Entity<Rejected>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Rejected");
});
modelBuilder.Entity<Modified>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Modified");
});
//this defined the principal-dependent relationship I was missing
modelBuilder.Entity<Action>()
.HasOptional(a => a.Result)
.WithRequired(a => a.Action)
.Map(x => x.MapKey("Action_Id"));
然后它起作用了!希望这个例子可以帮助别人。
推荐阅读
- microsoft-graph-api - 是否有任何有效的方法来查询列表下的唯一权限列表项(图形或 CSOM)?
- excel - 将数组添加在一起(在 VBA 中)以进行输出
- css - 平板媒体查询
- java - Twitter 中的 Get.text()
- java - Derby 将空表的现有列更改为标识
- java - 线程“主”java.lang.NoClassDefFoundError 中的异常:com/amazonaws/endpointdiscovery/EndpointDiscoveryProviderChain
- angular - 如何设置多个选项的默认选择值(离子选择)
- ssas - 无法恢复 2017 (1200) 2016 DB 中的表格模型(也是 1200)
- wpf - 为什么我的 Powershell WPF 数据绑定拉 System.Windows.Controls.ComboBoxItem: Test 1 而不是 Test 1
- maven - 强制maven使用本地依赖