定义EF中自引用List属性的列名
本文关键字:属性 List EF 自引用 定义 | 更新日期: 2023-09-27 17:53:50
我正在定义一个基于编目权限条目的类,它有许多自引用的子条目,如下所示:
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', ' broad '和' narrow '。我试过使用[列("名称")]属性,但它不起作用。我如何在"代码优先"中做到这一点?
试试这个。我不确定外键的定义是否必须在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; }
}
您可以使用[InverseProperty("name")]为您的列表。之后,您的列名将是"UsedFor_ID","Equilavent_ID"等在数据库中(不完全对应您的问题,对不起!)。
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/gg193958http://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx
谢谢你的建议。有效的方法是使用[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; }
}
为了防止级联删除,我还在我的数据库上下文中添加了以下内容(影响整个DB而不仅仅是这些表):
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
更新答案:
使用上面的给了我想要的底层表结构,但不是我需要的功能,因为EF决定在该配置下它将映射1-1关系而不是1-M。答案在于理解EntityFramework如何管理自引用的多对多关系。即使这样,也可以通过多种方式配置,这取决于您是只想要两个1m关系还是更多关系。我要六个
最后,这个配置为我提供了我想要的功能,代价是数据库结构不太理想。
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>();
}
}
我还需要将以下条目添加到数据库上下文的'OnModelCreating'过程中:
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();