简体   繁体   English

实体框架代码优先于隐含组合键的可选一对多关系

[英]Entity Framework Code First Optional One to Many Relationship on implied Composite Key

Update : Created a sample project on GitHub. 更新 :在GitHub上创建了一个示例项目

In my existing database I have a generic audit table that has no keys, but I'd like to insert into this audit table with EF code first. 在我现有的数据库中,我有一个没有密钥的通用审计表,但是我想先使用EF代码插入该审计表中。

Existing reports pull audits based on AffectedId and EntityId where EntityId is hardcoded in a bunch of places. 现有报告根据AffectedId和EntityId进行审核,其中EntityId在很多地方都进行了硬编码。
I reversed engineered the database, but there is no explicit relationship between these tables...so here are the base POCO objects (I can't make a relationship either, its an existing system) 我对数据库进行了反向工程,但是这些表之间没有明确的关系...所以这是基本的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; }
}

I think I want the POCO objects to look like this 我想我希望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; }
}

But I can't seem to get the fluent mapping to allow me to insert an Action (1 or 2) that has populated AffectedId's in the Audit. 但是我似乎无法获得流畅的映射以允许我在审计中插入已填充AffectedId的Action(1或2)。 This is what I was thinking on the mapping objects, but can't seem to get the hardcoded EntityId key to work correctly. 这就是我在映射对象上的想法,但似乎无法使硬编码的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);
    }
}

Any suggestions on how to change the C# and not the SQL would be appreciated. 关于如何更改C#而不是SQL的任何建议将不胜感激。

Mapping will not handle this scenario, but you can modify your domain model and business rules to do so. 映射不会处理这种情况,但是您可以修改域模型和业务规则来做到这一点。 And having an enum for your magic values for EntityId will be much better. 并且为您的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
}

Usage based on GitHub code dump 基于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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实体框架代码复合密钥的第一对一关系 - Entity Framework Code First One to One relationship on composite key 实体框架-代码优先-共享主键一对多关系 - Entity Framework - Code first - One to Many relationship with shared primary key 实体框架6 Code First一对多可选关系删除子问题 - Entity framework 6 Code First one-to-many optional relationship remove child issue Entity Framework 5.0代码首先是一对一和一对多的关系 - Entity Framework 5.0 code first one to one and one to many relationship 当一个实体具有复合主键时,Entity Framework Core 中的多对多关系 - Many-to-many relationship in Entity Framework Core when one entity has composite primary key 实体框架中的可选一对多关系 - Optional One-to-many Relationship in Entity Framework 实体框架代码优先的可选1:1关系 - Optional 1:1 relationship in Entity Framework Code First 映射一个到多个复合密钥实体框架5 - Map one to many composite key Entity framework 5 Code First Entity Framework不会创建一对多关系 - Code First Entity Framework doesn't create one to many relationship 无需代码优先模型创建的一对多关系实体框架 - One To Many relationship entity framework without Code First Model Creation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM