我正在定义一个基于编目权限条目的类,该条目具有许多自引用子级,如下所示:
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中做到这一点?
答案 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();