实体框架代码隐含复合密钥上的第一个可选一对多关系
本文关键字:第一个 关系 一对多 密钥 代码 框架 复合 实体 | 更新日期: 2023-09-27 18:24:41
更新:在GitHub上创建了一个示例项目。
在我现有的数据库中,我有一个没有键的通用审计表,但我想先用EF代码插入到这个审计表中。
现有报告基于AffectedId和EntityId提取审核,其中EntityId在一堆地方进行了硬编码
我对数据库进行了逆向工程,但这些表之间没有明确的关系。。。所以这里是基本的POCO对象(我也不能建立关系,它是一个现有的系统)
public class Audit
{
public int Id { get; set; }
public int EntityId { get; set; }
public string AffectedId { get; set; }
public string NewValue { get; set; }
}
public class Action1
{
public int Id { get; set; }
public string Desc { get; set; }
}
public class Action2
{
public int Id { get; set; }
public string Desc { get; set; }
}
我想我希望POCO对象看起来像这个
public class Audit
{
public int Id { get; set; }
public int EntityId { get; set; }
public string AffectedId { get; set; }
public string NewValue { get; set; }
public virtual Action1 Action1 { get; set; } // but I don't want this to change audit table
public virtual Action2 Action2 { get; set; } // but I don't want this to change audit table
}
public class Action1
{
public Action1() {this.Audits = new List<Audit>();}
public int Id { get; set; }
public string Desc { get; set; }
public virtual ICollection<Audit> Audits { get; set; }
}
public class Action2
{
public Action2() {this.Audits = new List<Audit>();}
public int Id { get; set; }
public string Desc { get; set; }
public virtual ICollection<Audit> Audits { get; set; }
}
但我似乎无法获得流畅的映射,无法插入已在Audit中填充AffectedId的Action(1或2)。这就是我对映射对象的想法,但似乎无法使硬编码的EntityId键正常工作。
public class AuditMap : EntityTypeConfiguration<Audit>
{
public AuditMap()
{
// Primary Key
this.HasKey(t => t.Id);
this.HasOptional(t => t.Action1)
.WithMany(t => t.Audits)
.HasForeignKey(t => new {EntityId = 3, AffectedId = t.Id});
this.HasOptional(t => t.Action2)
.WithMany(t => t.Audits)
.HasForeignKey(t => new {EntityId = 5, AffectedId = t.Id});
}
}
public class Action1 : EntityTypeConfiguration<Action1>
{
public Action1Map()
{
// Primary Key
this.HasKey(t => t.Id);
}
}
public class Action2 : EntityTypeConfiguration<Action2>
{
public Action2Map()
{
// Primary Key
this.HasKey(t => t.Id);
}
}
任何关于如何更改C#而不是SQL的建议都将不胜感激。
Mapping不会处理这种情况,但您可以修改域模型和业务规则来处理。为EntityId的神奇值设置一个枚举会更好。
public class Audit
{
public int Id { get; set; }
public int EntityId { get; set; }
public string AffectedId { get; set; }
public string NewValue { get; set; }
}
public abstract class AuditableAction{
public AuditableAction() {this.Audits = new List<Audit>();}
public int Id { get; set; }
public string Desc { get; set; }
public virtual IList<Audit> Audits { get; set; }
public void Audit(string description){
this.Audits.Add(new Audit(){
EntityId = this.GetEntityId(),
AffectedId = this.Id,
NewValue = description
});
}
public abstract int GetEntityId();
}
public class Action1 : AuditableAction
{
public override int GetEntityId(){
return AuditCode.Magic3.GetHashCode();
}
}
public class Action2 : AuditableAction
{
public override int GetEntityId(){
return AuditCode.Magic5.GetHashCode();
}
}
public enum AuditCode{
Magic3 = 3,
Magic5 = 5
}
基于GitHub代码转储的使用
using (var context = new yunoworkContext())
{
var a = new Action1() {Id = 4, Desc = Guid.NewGuid().ToString()};
// This audit should insert an audit with EntityId = 3 and AffectedId = {primary key of the assiciated Action1}
a.Audit("Console!");
context.SaveChanges();
}