在EF中为自引用List属性定义列名

时间:2016-07-01 22:02:36

标签: c# entity-framework attributes

我正在定义一个基于编目权限条目的类,该条目具有许多自引用子级,如下所示:

public class Authority
{
    public long ID { get; set; }
    public string Term { get; set; }
    public string Language { get; set; }
    public bool PreferredTerm  { get; set; }
    public TermStatus TermStatus { get; set; }
    public Authority Use { get; set; }
    public List<Authority> UsedFor { get; set; }
    public List<Authority> Equivalent { get; set; }
    public List<Authority> Broader { get; set; }
    public List<Authority> Narrower { get; set; }
}

在基础SQL数据库的Authority表中创建列时,每个List属性的列名称为Authority_ID,Authority_ID1,Authority_ID2和Authority_ID3。

我希望列名称为'UsedFor','Equivalent','Broader'和'Narrower'。我尝试使用[Column(“name”)]属性,但它不起作用。我怎么能在Code First中做到这一点?

4 个答案:

答案 0 :(得分:0)

试试这个。我不确定外键的定义是否必须在POCO类中(您可以尝试省略它们)。

public class Authority
{
    [Key()]
    public long ID { get; set; }
    public string Term { get; set; }
    public string Language { get; set; }
    public bool PreferredTerm  { get; set; }
    public TermStatus TermStatus { get; set; }
    public Authority Use { get; set; }

    [Required]
    public long Authority_ID { get; set; }

    [Required]
    public long Authority_ID1 { get; set; }

    [Required]
    public long Authority_ID2 { get; set; }

    [Required]
    public long Authority_ID3 { get; set; }

    [ForeignKey("Authority_ID")]
    public ICollection<Authority> UsedFor { get; set; }

    [ForeignKey("Authority_ID1")]
    public ICollection<Authority> Equivalent { get; set; }

    [ForeignKey("Authority_ID2")]
    public ICollection<Authority> Broader { get; set; }

    [ForeignKey("Authority_ID3")]
    public ICollection<Authority> Narrower { get; set; }
}

答案 1 :(得分:0)

您可以使用[InverseProperty(&#34; name&#34;)]作为列表。之后,您的列名将在数据库中为&#34; UsedFor_ID&#34;,&#34; Equilavent_ID&#34;等等(不完全对应您的问题,抱歉!)。

public class Authority
{
    [InverseProperty("UsedFor")]    
    public List<Authority> UsedFor { get; set; }
    [InverseProperty("Equivalent")]  
    public List<Authority> Equivalent { get; set; }    
}

详情请见: https://msdn.microsoft.com/en-us/data/gg193958 http://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx

答案 2 :(得分:0)

感谢您的建议。有用的是使用[ForeignKey]作为链接,使用[Column]重命名该列,即

    [Column("Use")]
    public long? UseID { get; set; }

    [ForeignKey("UseID")]
    public List<Authority> Use { get; set; }

但是我在定义中也犯了一个严重的错误,因为即使我将列定义为List,上面的代码也会以1到0/1的密钥结束。我真正需要做的是添加一个子表来接受许多值。

我的最终代码如下所示,基础列名称是可读的,而不是Authority_ID,Authority_ID1,Authority_ID2和Authority_ID3:

public class Authority
{
    public long ID { get; set; }
    public string Term { get; set; }
    public string Language { get; set; }
    public bool PreferredTerm  { get; set; }
    public TermStatus TermStatus { get; set; }

    //Establish 1-to-0/1 self-referencing key
    [Column("Use")]
    public long? UseID { get; set; }

    [ForeignKey("UseID")]
    public List<Authority> Use { get; set; }

    //Establis 1-many foreign keys
    [ForeignKey("UsedFor")]
    public List<AuthorityList> UsedFor { get; set; }

    [ForeignKey("Equivalent")]
    public List<AuthorityList> Equivalent { get; set; }

    [ForeignKey("Broader")]
    public List<AuthorityList> Broader { get; set; }

    [ForeignKey("Narrower")]
    public List<AuthorityList> Narrower { get; set; }
}

public class AuthorityList
{
    public long ID { get; set; }
    public long AuthorityID { get; set; }
    public long? UsedFor { get; set; }
    public long? Equivalent { get; set; }
    public long? Broader { get; set; }
    public long? Narrower { get; set; }
}

为了防止级联删除的方式,我还将以下内容添加到我的数据库上下文中(影响整个数据库而不仅仅是这些表):

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

答案 3 :(得分:0)

更新回答

使用上面给出了我想要的基础表结构但不是我需要的功能,因为EF决定在该配置下它将映射1-1关系而不是1-M。答案在于理解EntityFramework如何管理自引用多对多关系。即使这样也可以通过多种方式配置,具体取决于您是否只需要两个1-M关系或更多。我想要六个。

最后,这种配置为我提供了我想要的功能,但却牺牲了不太理想的数据库结构。

public class Tag
{
    public int ID { get; set; }
    public string Term { get; set; }

    public virtual ICollection<Tag> Broader { get; set; }
    public virtual ICollection<Tag> Narrower { get; set; }
    public virtual ICollection<Tag> Equivalent { get; set; }
    public virtual ICollection<Tag> Related { get; set; }
    public virtual ICollection<Tag> Use { get; set; }
    public virtual ICollection<Tag> Usefor { get; set; }

    public Tag()
    {
        Broader = new HashSet<Tag>();
        Narrower = new HashSet<Tag>();
        Equivalent = new HashSet<Tag>();
        Related = new HashSet<Tag>();
        Use = new HashSet<Tag>();
        Usefor = new HashSet<Tag>();
    }
}

我还需要将以下条目添加到&#39; OnModelCreating&#39;数据库上下文的过程:

    modelBuilder.Entity<Tag>()
        .HasMany(x => x.Broader)
        .WithMany()
        .Map(x => x.MapLeftKey("TagID").MapRightKey("BroaderID").ToTable("TagBroader"));

    modelBuilder.Entity<Tag>()
        .HasMany(x => x.Equivalent)
        .WithMany()
        .Map(x => x.MapLeftKey("TagID").MapRightKey("EquivalentID").ToTable("TagEquivalent"));

    modelBuilder.Entity<Tag>()
        .HasMany(x => x.Narrower)
        .WithMany()
        .Map(x => x.MapLeftKey("TagID").MapRightKey("NarrowerID").ToTable("TagNarrower"));

    modelBuilder.Entity<Tag>()
            .HasMany(x => x.Related)
            .WithMany()
            .Map(x => x.MapLeftKey("TagID").MapRightKey("RelatedID").ToTable("TagRelated"));

    modelBuilder.Entity<Tag>()
        .HasMany(x => x.Use)
        .WithMany()
        .Map(x => x.MapLeftKey("TagID").MapRightKey("UsedID").ToTable("TagUse"));

    modelBuilder.Entity<Tag>()
        .HasMany(x => x.Usedfor)
        .WithMany()
        .Map(x => x.MapLeftKey("TagID").MapRightKey("UsedforID").ToTable("TagUsedfor"));

为了测试,我使用了以下内容:

        //Broader/Narrower example
        var music = new Tag{ Term = "Music"};
        var jazz = new Tag{ Term = "Jazz Music" };
        var classical = new Tag{ Term = "Classical Music" };

        music.Narrower.Add(jazz);
        music.Narrower.Add(classical);
        jazz.Broader.Add(music);
        classical.Broader.Add(music);

        //Equivalent example
        var zucchini = new Tag{ Term = "Zucchini" };
        var courgette = new Tag{ Term = "Courgette" };

        zucchini.Equivalent.Add(courgette);
        courgette.Equivalent.Add(zucchini);

        context.Tags.Add(music);
        context.Tags.Add(jazz);
        context.Tags.Add(classical);
        context.Tags.Add(zucchini);
        context.Tags.Add(courgette);
        context.SaveChanges();