C# 外键依赖于另一个外键,因为它';s父密钥

C# 外键依赖于另一个外键,因为它';s父密钥,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我正在创建一个库,作为其他项目的基础,可以找到项目的详细信息,也可以找到nuget包 因为这是一个基本库,我想允许用户扩展模型,所以我创建的是接口,而不是具体的库(默认实现显然存在,但这超出了当前问题的范围),但由于实体框架只能用具体的类来完成导航/外键,我正在经历通用接口的过程,它工作得很好,但是我已经达到了一个点,我想基于同一个表中的另一个外键来限制外键 在寻找答案时,这个问题最接近我的要求 这里提供的解决方案说,从技术上讲,您应该删除父表键,因为子表已经有了可以用来关联到父表的父表键,我

我正在创建一个库,作为其他项目的基础,可以找到项目的详细信息,也可以找到nuget包

因为这是一个基本库,我想允许用户扩展模型,所以我创建的是接口,而不是具体的库(默认实现显然存在,但这超出了当前问题的范围),但由于实体框架只能用具体的类来完成导航/外键,我正在经历通用接口的过程,它工作得很好,但是我已经达到了一个点,我想基于同一个表中的另一个外键来限制外键

在寻找答案时,这个问题最接近我的要求

这里提供的解决方案说,从技术上讲,您应该删除父表键,因为子表已经有了可以用来关联到父表的父表键,我完全同意这一点,然而,在我的例子中,这是不可能的,因为它将导致循环依赖地狱,这是应该不惜一切代价远离软件项目的东西

i组织界面

public interface IOrganization<TLinkedAddress> where TLinkedAddress : ILinkedAddress
{
    long ID { get; set; }
    string Name { get; set; }
    string Brand { get; set; }
    string Genre { get; set; }
    string Industry { get; set; }
    string Master_Security_Stamp { get; set; }
    long? Control_Branch_ID { get; set; }

    [ForeignKey("Control_Branch_ID")]
    TLinkedAddress Control_Branch { get; set; }

    IList<TLinkedAddress> Branches { get; set; }
}
public interface ILinkedAddress
{
    long ID { get; set; }
    string Address { get; set; }
    long LocationID { get; set; }
    string AddressType { get; set; }
    string Contact_Person_Name { get; set; }
    string Contact_Person_Number { get; set; }
    string Contact_Person_Relation { get; set; }
    [ForeignKey("OrganizationID")]
    long? OrganizationID { get; set; }
    [ForeignKey("UserID")]
    long? UserID { get; set; }
}
public interface IEducation<TUser, TOrganization, TLinkedAddress>
    where TUser : IUser
    where TOrganization : IOrganization<TLinkedAddress>
    where TLinkedAddress : ILinkedAddress
{
    long ID { get; set; }
    long UserID { get; set; }
    long InstituteID { get; set; }
    long InstituteLocationID { get; set; }
    string Degree { get; set; }
    string Major { get; set; }
    string Grade { get; set; }
    DateTime StartDate { get; set; }
    DateTime? EndDate { get; set; }
    string Socities { get; set; }
    string Description { get; set; }

    [ForeignKey(name: "UserID")]
    TUser User { get; set; }
    [ForeignKey(name: "InstituteID")]
    TOrganization Institute { get; set; }
    [ForeignKey(name: "InstituteLocationID")]
    TLinkedAddress InstituteLocation { get; set; }
}
i教育界面

public interface IOrganization<TLinkedAddress> where TLinkedAddress : ILinkedAddress
{
    long ID { get; set; }
    string Name { get; set; }
    string Brand { get; set; }
    string Genre { get; set; }
    string Industry { get; set; }
    string Master_Security_Stamp { get; set; }
    long? Control_Branch_ID { get; set; }

    [ForeignKey("Control_Branch_ID")]
    TLinkedAddress Control_Branch { get; set; }

    IList<TLinkedAddress> Branches { get; set; }
}
public interface ILinkedAddress
{
    long ID { get; set; }
    string Address { get; set; }
    long LocationID { get; set; }
    string AddressType { get; set; }
    string Contact_Person_Name { get; set; }
    string Contact_Person_Number { get; set; }
    string Contact_Person_Relation { get; set; }
    [ForeignKey("OrganizationID")]
    long? OrganizationID { get; set; }
    [ForeignKey("UserID")]
    long? UserID { get; set; }
}
public interface IEducation<TUser, TOrganization, TLinkedAddress>
    where TUser : IUser
    where TOrganization : IOrganization<TLinkedAddress>
    where TLinkedAddress : ILinkedAddress
{
    long ID { get; set; }
    long UserID { get; set; }
    long InstituteID { get; set; }
    long InstituteLocationID { get; set; }
    string Degree { get; set; }
    string Major { get; set; }
    string Grade { get; set; }
    DateTime StartDate { get; set; }
    DateTime? EndDate { get; set; }
    string Socities { get; set; }
    string Description { get; set; }

    [ForeignKey(name: "UserID")]
    TUser User { get; set; }
    [ForeignKey(name: "InstituteID")]
    TOrganization Institute { get; set; }
    [ForeignKey(name: "InstituteLocationID")]
    TLinkedAddress InstituteLocation { get; set; }
}
公共接口教育
图瑟:尤瑟
组织所在地:I组织
地址:ILinkedAddress:ILinkedAddress
{
长ID{get;set;}
长用户标识{get;set;}
长机构ID{get;set;}
long InstituteLocationID{get;set;}
字符串度{get;set;}
字符串主键{get;set;}
字符串级别{get;set;}
DateTime开始日期{get;set;}
DateTime?EndDate{get;set;}
字符串社团{get;set;}
字符串说明{get;set;}
[外键(名称:“UserID”)]
TUser用户{get;set;}
[ForeignKey(名称:“InstituteID”)]
组织研究所{get;set;}
[ForeignKey(名称:“InstituteLocationID”)]
TLinkedAddress机构位置{get;set;}
}
默认实现

[Table(name: "LinkedAddress", Schema = "Arinsys_CRM")]
public class LinkedAddress : DBEntity<LinkedAddress>, ILinkedAddress
{
    public long ID { get; set; }
    public string Address { get; set; }
    public long LocationID { get; set; }
    public string AddressType { get; set; }
    public string Contact_Person_Name { get; set; }
    public string Contact_Person_Number { get; set; }
    public string Contact_Person_Relation { get; set; }
    [ForeignKey("OrganizationID")]
    public long? OrganizationID { get; set; }
    [ForeignKey("UserID")]
    public long? UserID { get; set; }
}
[Table(name: "Organization", Schema = "Arinsys_CRM")]
public partial class Organization : DataContext.DBEntity<Organization>,
    IOrganization<LinkedAddress>
{
    public long ID { get; set; }
    public string Name { get; set; }
    public string Brand { get; set; }
    public string Genre { get; set; }
    public string Industry { get; set; }
    public string Master_Security_Stamp { get; set; }
    public long? Control_Branch_ID { get; set; }

    [ForeignKey("Control_Branch_ID")]
    public virtual LinkedAddress Control_Branch { get; set; }

    public virtual IList<LinkedAddress> Branches { get; set; }
}
[Table(name: "Education", Schema = "Arinsys_CRM")]
public class Education : IEducation<User, Organization, LinkedAddress>
{
    public long ID { get; set; }
    public long UserID { get; set; }
    public long InstituteID { get; set; }
    public long InstituteLocationID { get; set; }
    public string Degree { get; set; }
    public string Major { get; set; }
    public string Grade { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public string Socities { get; set; }
    public string Description { get; set; }

    [ForeignKey(name: "UserID")]
    public virtual User User { get; set; }
    [ForeignKey(name: "InstituteID")]
    public virtual Organization Institute { get; set; }
    [ForeignKey(name: "InstituteLocationID")]
    public virtual LinkedAddress InstituteLocation { get; set; }
}
LinkedAddress.cs

[Table(name: "LinkedAddress", Schema = "Arinsys_CRM")]
public class LinkedAddress : DBEntity<LinkedAddress>, ILinkedAddress
{
    public long ID { get; set; }
    public string Address { get; set; }
    public long LocationID { get; set; }
    public string AddressType { get; set; }
    public string Contact_Person_Name { get; set; }
    public string Contact_Person_Number { get; set; }
    public string Contact_Person_Relation { get; set; }
    [ForeignKey("OrganizationID")]
    public long? OrganizationID { get; set; }
    [ForeignKey("UserID")]
    public long? UserID { get; set; }
}
[Table(name: "Organization", Schema = "Arinsys_CRM")]
public partial class Organization : DataContext.DBEntity<Organization>,
    IOrganization<LinkedAddress>
{
    public long ID { get; set; }
    public string Name { get; set; }
    public string Brand { get; set; }
    public string Genre { get; set; }
    public string Industry { get; set; }
    public string Master_Security_Stamp { get; set; }
    public long? Control_Branch_ID { get; set; }

    [ForeignKey("Control_Branch_ID")]
    public virtual LinkedAddress Control_Branch { get; set; }

    public virtual IList<LinkedAddress> Branches { get; set; }
}
[Table(name: "Education", Schema = "Arinsys_CRM")]
public class Education : IEducation<User, Organization, LinkedAddress>
{
    public long ID { get; set; }
    public long UserID { get; set; }
    public long InstituteID { get; set; }
    public long InstituteLocationID { get; set; }
    public string Degree { get; set; }
    public string Major { get; set; }
    public string Grade { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public string Socities { get; set; }
    public string Description { get; set; }

    [ForeignKey(name: "UserID")]
    public virtual User User { get; set; }
    [ForeignKey(name: "InstituteID")]
    public virtual Organization Institute { get; set; }
    [ForeignKey(name: "InstituteLocationID")]
    public virtual LinkedAddress InstituteLocation { get; set; }
}
[表(名称:“LinkedAddress”,Schema=“Arinsys\u CRM”)]
公共类LinkedAddress:DBEntity,ILinkedAddress
{
公共长ID{get;set;}
公共字符串地址{get;set;}
公共长位置ID{get;set;}
公共字符串地址类型{get;set;}
公共字符串Contact_Person_Name{get;set;}
公共字符串Contact_Person_Number{get;set;}
公共字符串联系人\个人\关系{get;set;}
[外键(“组织ID”)]
公共长?组织ID{get;set;}
[外键(“用户ID”)]
public long?UserID{get;set;}
}
Organization.cs

[Table(name: "LinkedAddress", Schema = "Arinsys_CRM")]
public class LinkedAddress : DBEntity<LinkedAddress>, ILinkedAddress
{
    public long ID { get; set; }
    public string Address { get; set; }
    public long LocationID { get; set; }
    public string AddressType { get; set; }
    public string Contact_Person_Name { get; set; }
    public string Contact_Person_Number { get; set; }
    public string Contact_Person_Relation { get; set; }
    [ForeignKey("OrganizationID")]
    public long? OrganizationID { get; set; }
    [ForeignKey("UserID")]
    public long? UserID { get; set; }
}
[Table(name: "Organization", Schema = "Arinsys_CRM")]
public partial class Organization : DataContext.DBEntity<Organization>,
    IOrganization<LinkedAddress>
{
    public long ID { get; set; }
    public string Name { get; set; }
    public string Brand { get; set; }
    public string Genre { get; set; }
    public string Industry { get; set; }
    public string Master_Security_Stamp { get; set; }
    public long? Control_Branch_ID { get; set; }

    [ForeignKey("Control_Branch_ID")]
    public virtual LinkedAddress Control_Branch { get; set; }

    public virtual IList<LinkedAddress> Branches { get; set; }
}
[Table(name: "Education", Schema = "Arinsys_CRM")]
public class Education : IEducation<User, Organization, LinkedAddress>
{
    public long ID { get; set; }
    public long UserID { get; set; }
    public long InstituteID { get; set; }
    public long InstituteLocationID { get; set; }
    public string Degree { get; set; }
    public string Major { get; set; }
    public string Grade { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public string Socities { get; set; }
    public string Description { get; set; }

    [ForeignKey(name: "UserID")]
    public virtual User User { get; set; }
    [ForeignKey(name: "InstituteID")]
    public virtual Organization Institute { get; set; }
    [ForeignKey(name: "InstituteLocationID")]
    public virtual LinkedAddress InstituteLocation { get; set; }
}
[表(名称:“组织”,Schema=“Arinsys\u CRM”)]
公共部分类组织:DataContext.DBEntity,
组织
{
公共长ID{get;set;}
公共字符串名称{get;set;}
公共字符串品牌{get;set;}
公共字符串类型{get;set;}
公共字符串行业{get;set;}
公共字符串Master_Security_Stamp{get;set;}
公共长?控制分支ID{get;set;}
[ForeignKey(“控制分支机构ID”)]
公共虚拟链接地址控件_分支{get;set;}
公共虚拟IList分支{get;set;}
}
Education.cs

[Table(name: "LinkedAddress", Schema = "Arinsys_CRM")]
public class LinkedAddress : DBEntity<LinkedAddress>, ILinkedAddress
{
    public long ID { get; set; }
    public string Address { get; set; }
    public long LocationID { get; set; }
    public string AddressType { get; set; }
    public string Contact_Person_Name { get; set; }
    public string Contact_Person_Number { get; set; }
    public string Contact_Person_Relation { get; set; }
    [ForeignKey("OrganizationID")]
    public long? OrganizationID { get; set; }
    [ForeignKey("UserID")]
    public long? UserID { get; set; }
}
[Table(name: "Organization", Schema = "Arinsys_CRM")]
public partial class Organization : DataContext.DBEntity<Organization>,
    IOrganization<LinkedAddress>
{
    public long ID { get; set; }
    public string Name { get; set; }
    public string Brand { get; set; }
    public string Genre { get; set; }
    public string Industry { get; set; }
    public string Master_Security_Stamp { get; set; }
    public long? Control_Branch_ID { get; set; }

    [ForeignKey("Control_Branch_ID")]
    public virtual LinkedAddress Control_Branch { get; set; }

    public virtual IList<LinkedAddress> Branches { get; set; }
}
[Table(name: "Education", Schema = "Arinsys_CRM")]
public class Education : IEducation<User, Organization, LinkedAddress>
{
    public long ID { get; set; }
    public long UserID { get; set; }
    public long InstituteID { get; set; }
    public long InstituteLocationID { get; set; }
    public string Degree { get; set; }
    public string Major { get; set; }
    public string Grade { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public string Socities { get; set; }
    public string Description { get; set; }

    [ForeignKey(name: "UserID")]
    public virtual User User { get; set; }
    [ForeignKey(name: "InstituteID")]
    public virtual Organization Institute { get; set; }
    [ForeignKey(name: "InstituteLocationID")]
    public virtual LinkedAddress InstituteLocation { get; set; }
}
[表(名称:“教育”,Schema=“Arinsys\u CRM”)]
公营教育:教育
{
公共长ID{get;set;}
公共长用户标识{get;set;}
公共长机构ID{get;set;}
公共长期机构定位ID{get;set;}
公共字符串度数{get;set;}
公共字符串主键{get;set;}
公共字符串等级{get;set;}
公共日期时间起始日期{get;set;}
公共日期时间?结束日期{get;set;}
公共字符串社团{get;set;}
公共字符串说明{get;set;}
[外键(名称:“UserID”)]
公共虚拟用户用户{get;set;}
[ForeignKey(名称:“InstituteID”)]
公共虚拟组织机构{get;set;}
[ForeignKey(名称:“InstituteLocationID”)]
公共虚拟链接地址机构位置{get;set;}
}
现在的问题是,在
IEducation
接口中,是否有可能对
instituteLocationID
施加约束,即它必须是
组织的一个分支,由
InstituteID
定义,否则我将别无选择,只能让最终开发人员自己施加约束

编辑:进一步研究

我开始研究@Ivan Starostin建议的可传递依赖关系,并偶然发现@Jeff Atwood(Stack Overflow的联合创始人(荣誉退休人员)和联合创始人)关于他们在2008年面临的堆栈溢出问题的这篇很棒的博文


这篇博文的总结是,规范化并不是万能的,有时非规范化的数据实际上会带来更好的生产力和性能,尽管这篇博文没有回答确切的问题,但它帮助我获得了更深入的理解,所以在这里为未来的读者发帖。

这是一个有点理论性的问题。InstituteID不是教育实体的属性,而是LinkedLocation实体的属性。所以你在教育实体中有一个传递依赖,这意味着它不是第三范式:InstituteID依赖于InstituteLocationID。因此,您必须将InstituteID视为无关系约束的非规范化数据,或者将其从教育实体中删除。此外,我认为问题来自LinkedAddress实体-它是地址实体和附加链接实体的混合体,应该存储地址和组织之间的链接。所以,如果您从LinkedAddress提取实体地址,并使LinkedAddress成为一个真正的链接实体,它存储AddressID和OrganizationID的元组,这可能会使模型更加清晰,并显示InstituteLocation