【问题标题】:Entity Framework Code First Optional One to Many Relationship on implied Composite Key实体框架代码优先隐含复合键上的可选一对多关系
【发布时间】:2013-07-24 20:38:22
【问题描述】:

更新:在 GitHub 上创建了 sample project

在我现有的数据库中,我有一个没有键的通用审计表,但我想先用 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; }
}

但我似乎无法获得流畅的映射以允许我在审核中插入已填充 AffectedId 的操作(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 的建议将不胜感激。

【问题讨论】:

  • EntityId 总是 3 和 5 吗?
  • 是的,它们是任意标识符,不会更改,但对于操作是唯一的。可以有更多具有自己不变的任意唯一标识符的操作。
  • 好的,我根据你的 Github 代码修改了答案

标签: c# entity-framework entity-framework-5


【解决方案1】:

映射不会处理这种情况,但您可以修改您的域模型和业务规则来执行此操作。并且为 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();
}

【讨论】:

  • 还有一个变体,如果每个动作只有一个 EntityId 与之关联会更好。
  • 太好了,我更新了示例以更好地封装 entityid。
  • AffectedId = this.Id 无法解析。因此向名为 Id 的类添加了一个抽象属性。这试图向数据库添加一列(错误是“无效的列名'Action1_Id'”。(我在 github 项目中创建了一个分支并发布了更改)。我错过了什么吗?感谢您的帮助。
  • 抱歉,我没有正确移动所有属性。
  • 这仍在尝试向 Audit 表中添加列,但我做不到。这将为每个操作类型的审计表添加一列。此外,affectedId 始终为 0。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多