实现一对零或一对一关系和一对多关系 Class
Implementing a One-to-Zero-or-One Relationship and a One-to-Many Relationship of the Same Class
我在映射以下 class 时遇到问题。
我希望 MainAboutPage
是可选的(一对零或一对一)并且 AboutSubPages
显然是一对多。
理想情况下,我想将 WebsiteId
属性 保留在 WebsitePage
class 上。
public class Website
{
public int Id { get; set; }
public virtual WebsitePage MainAboutPage { get; set; }
public ICollection<WebsitePage> AboutSubPages { get; set; }
}
public class WebsitePage
{
public int Id { get; set; }
public int WebsiteId { get; set; }
public virtual Website Website { get; set; }
}
当我不使用流畅的映射时,我得到
Unable to determine the principal end of the relationship. Multiple added entities may have the same primary key.
当我使用这种流畅的映射时:
modelBuilder.Entity<Wesbite>()
.HasMany(x => x.AboutSubPages)
.WithRequired(x => x.Website)
.HasForeignKey(x => x.WebsiteId);
我得到:
Unable to determine the principal end of the 'Wesbite_AboutSubPages' relationship. Multiple added entities may have the same primary key.
当我使用这种流畅的映射时:
modelBuilder.Entity<Website>()
.HasOptional(x => x.MainAboutPage)
.WithRequired();
modelBuilder.Entity<Wesbite>()
.HasMany(x => x.AboutSubPages)
.WithRequired(x => x.Website)
.HasForeignKey(x => x.WebsiteId);
我得到:
Unable to determine the principal end of the 'Website_MainAboutPage' relationship. Multiple added entities may have the same primary key.
当我使用这种流畅的映射时:
modelBuilder.Entity<Website>()
.HasOptional(x => x.MainAboutPage)
.WithRequired(x => x.Website);
modelBuilder.Entity<Wesbite>()
.HasMany(x => x.AboutSubPages)
.WithRequired(x => x.Website)
.HasForeignKey(x => x.WebsiteId);
我得到:
Wesbite_MainAboutPage_Target: : Multiplicity is not valid in Role 'Wesbite_MainAboutPage_Target' in relationship 'Website_MainAboutPage'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
我一直在无休止地阅读来自 MS 的配置示例:https://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx and https://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx
我的大脑被腌制了,如果我遗漏了一些明显的东西,请原谅。我真的很感激一些关于如何按照我的意愿进行设置的指示。
提前致谢。
我认为问题在于您没有足够的信息让 EF 区分与网站相关的 AboutSubPages 和 MainAboutPage 引用。要在网站上与 MainAboutPage 建立 1..0/1 关系,您需要在网站 table 中声明 MainAboutPageId。
modelBuilder.Entity<Website>()
.HasOptional(x => x.MainAboutPage)
.WithRequired(x => x.Website)
.HasForeignKey(x => x.MainAboutPageId);
或者您可以选择使用 Shadow 属性 (EF Core) 或 Map.MapKey
(EF6) 来映射关系,而不会在实体中公开 FK。 (推荐)
同时具有 1..0/1 加 1..many of 实体关系到相同相关实体的警告是无法强制 MainAboutPage 实际上属于子集合。因为 1..0/1 依赖于从网页到子页面的 FK,所以没有强制要求子页面必须指向同一网站。 EF 和数据库非常高兴让 WebSite ID #1 指向具有 WebSite ID #2 的子页面。
更好的方法可能是只维护一个 AboutSubPages 集合并向 SubPage 实体添加一个 PageOrder 数字唯一索引。例如,"main" 子页面将是具有最低 PageOrder 的子页面。
即select 一个网站的详细信息,它 "main" 关于页面:
var websites = context.Websites
.Select(x => new WebsiteSummaryViewModel
{
Name = x.Name,
AboutPageURL = x.AboutSubPages
.OrderBy(a => a.PageOrder)
.Select(a => a.Url)
.FirstOrDefault()
}).ToList();
... 举个例子。这确保我们可以访问主页,同时确保网站认为唯一的页面是分配给它的页面。可以在网站实体上将未映射的 属性 设置为嵌入式集合中的 return "MainAboutPage",但是我不建议使用未映射的属性,因为它们很容易滑入 Linq表达式和 EF 将引发异常或执行过早执行 (EF Core) 来解决它们。
我在映射以下 class 时遇到问题。
我希望 MainAboutPage
是可选的(一对零或一对一)并且 AboutSubPages
显然是一对多。
理想情况下,我想将 WebsiteId
属性 保留在 WebsitePage
class 上。
public class Website
{
public int Id { get; set; }
public virtual WebsitePage MainAboutPage { get; set; }
public ICollection<WebsitePage> AboutSubPages { get; set; }
}
public class WebsitePage
{
public int Id { get; set; }
public int WebsiteId { get; set; }
public virtual Website Website { get; set; }
}
当我不使用流畅的映射时,我得到
Unable to determine the principal end of the relationship. Multiple added entities may have the same primary key.
当我使用这种流畅的映射时:
modelBuilder.Entity<Wesbite>()
.HasMany(x => x.AboutSubPages)
.WithRequired(x => x.Website)
.HasForeignKey(x => x.WebsiteId);
我得到:
Unable to determine the principal end of the 'Wesbite_AboutSubPages' relationship. Multiple added entities may have the same primary key.
当我使用这种流畅的映射时:
modelBuilder.Entity<Website>()
.HasOptional(x => x.MainAboutPage)
.WithRequired();
modelBuilder.Entity<Wesbite>()
.HasMany(x => x.AboutSubPages)
.WithRequired(x => x.Website)
.HasForeignKey(x => x.WebsiteId);
我得到:
Unable to determine the principal end of the 'Website_MainAboutPage' relationship. Multiple added entities may have the same primary key.
当我使用这种流畅的映射时:
modelBuilder.Entity<Website>()
.HasOptional(x => x.MainAboutPage)
.WithRequired(x => x.Website);
modelBuilder.Entity<Wesbite>()
.HasMany(x => x.AboutSubPages)
.WithRequired(x => x.Website)
.HasForeignKey(x => x.WebsiteId);
我得到:
Wesbite_MainAboutPage_Target: : Multiplicity is not valid in Role 'Wesbite_MainAboutPage_Target' in relationship 'Website_MainAboutPage'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
我一直在无休止地阅读来自 MS 的配置示例:https://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx and https://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx
我的大脑被腌制了,如果我遗漏了一些明显的东西,请原谅。我真的很感激一些关于如何按照我的意愿进行设置的指示。
提前致谢。
我认为问题在于您没有足够的信息让 EF 区分与网站相关的 AboutSubPages 和 MainAboutPage 引用。要在网站上与 MainAboutPage 建立 1..0/1 关系,您需要在网站 table 中声明 MainAboutPageId。
modelBuilder.Entity<Website>()
.HasOptional(x => x.MainAboutPage)
.WithRequired(x => x.Website)
.HasForeignKey(x => x.MainAboutPageId);
或者您可以选择使用 Shadow 属性 (EF Core) 或 Map.MapKey
(EF6) 来映射关系,而不会在实体中公开 FK。 (推荐)
同时具有 1..0/1 加 1..many of 实体关系到相同相关实体的警告是无法强制 MainAboutPage 实际上属于子集合。因为 1..0/1 依赖于从网页到子页面的 FK,所以没有强制要求子页面必须指向同一网站。 EF 和数据库非常高兴让 WebSite ID #1 指向具有 WebSite ID #2 的子页面。
更好的方法可能是只维护一个 AboutSubPages 集合并向 SubPage 实体添加一个 PageOrder 数字唯一索引。例如,"main" 子页面将是具有最低 PageOrder 的子页面。
即select 一个网站的详细信息,它 "main" 关于页面:
var websites = context.Websites
.Select(x => new WebsiteSummaryViewModel
{
Name = x.Name,
AboutPageURL = x.AboutSubPages
.OrderBy(a => a.PageOrder)
.Select(a => a.Url)
.FirstOrDefault()
}).ToList();
... 举个例子。这确保我们可以访问主页,同时确保网站认为唯一的页面是分配给它的页面。可以在网站实体上将未映射的 属性 设置为嵌入式集合中的 return "MainAboutPage",但是我不建议使用未映射的属性,因为它们很容易滑入 Linq表达式和 EF 将引发异常或执行过早执行 (EF Core) 来解决它们。