类/数据库的循环引用(C#,首先是实体框架代码)

类/数据库的循环引用(C#,首先是实体框架代码),c#,entity-framework,database-design,ef-code-first,circular-reference,C#,Entity Framework,Database Design,Ef Code First,Circular Reference,如果没有循环引用,是否有更好的设计?有什么问题吗? 课程包括: public class Stat { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public List<Quantity> Quantities { get; set; } public List<Hit>

如果没有循环引用,是否有更好的设计?有什么问题吗? 课程包括:

public class Stat
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public List<Quantity> Quantities { get; set; }
    public List<Hit> Hits { get; set; }
}
public class Hit
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public string Comment { get; set; }

    public virtual Stat Stat { get; set; }
    public List<HitComponent> HitComponents { get; set; }
}
public class HitComponent
{
    public int Id { get; set; }
    public float Amount { get; set; }

    public virtual Hit Hit { get; set; }
    public virtual Quantity Quantity { get; set; }
}
public class Quantity
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Stat Stat { get; set; }
    public virtual Unit Unit { get; set; }
    public List<HitComponent> HitComponents { get; set; }
}
public class Unit
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Abbreviation { get; set; }

    public List<Quantity> Quantities { get; set; }
}
公共类统计
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串说明{get;set;}
公共列表数量{get;set;}
公共列表命中{get;set;}
}
公课热门
{
公共int Id{get;set;}
公共日期时间日期{get;set;}
公共字符串注释{get;set;}
公共虚拟Stat{get;set;}
公共列表组件{get;set;}
}
公共类组件
{
公共int Id{get;set;}
公共浮动金额{get;set;}
公共虚拟命中{get;set;}
公共虚拟数量{get;set;}
}
公共类数量
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共虚拟Stat{get;set;}
公共虚拟单元单元{get;set;}
公共列表组件{get;set;}
}
公营课组
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串缩写{get;set;}
公共列表数量{get;set;}
}
统计数据是对某些事物的统计,例如举重等训练运动。数量可以是可以用数字测量的东西,例如所用杠铃的重量(单位为千克-单位存储在单位类中),或者重复次数。在这种情况下,Stat(举重)有两个量(重量、重复次数)。命中是一个统计事件(一次举重训练)。HitComponent属于命中,它包含一个数量的数量。每一次命中必须包含尽可能多的命中成分和命中属性所包含的数量。(例如,每个“举重”属性的命中必须包含两个命中组件,一个用于“重量”数量,一个用于“重复”数量。我怀疑,可能这个前提条件会导致一些问题…)

我使用上面显示的设计,没有太多问题——只是循环引用有点笨拙——只要我想将一些类序列化为Json字符串,因为这会导致循环引用异常

我的第一个问题是这个设计有什么问题吗?我在谷歌上搜索了很多,没有找到这种循环引用的明确答案(有人说它不是真正的循环引用,因为方向不是“循环的”,有人说这个解决方案很有问题)?
另一个问题是有人能提出更好的设计吗?

循环引用并不是那么邪恶。如果你看,你的引用只是虚拟的(你的列表也应该是虚拟的),所以实际上它更倾向于保留在任何方向跟随引用的能力。根据EF的定义或设计,这会创建一个“循环参考”,这只是一个副作用

只有当您尝试序列化包含两个导航属性的对象时,这些循环引用才会出现问题。在这种情况下,您必须指示序列化程序跳过其中一个导航方向,以便删除循环引用

根据序列化程序的不同,忽略导航属性的方式也不同。通过使用Json(var)时使用的普通序列化程序(JavaScriptSerializer),您可以在属性上使用
[ScriptIgnore]
属性,您希望在序列化过程中不遵循该属性

例如,从Stat到Hit删除循环引用

public class Stat
{
 public int Id { get; set; }
 public string Name { get; set; }
 public string Description { get; set; }

 public virtual List<Quantity> Quantities { get; set; }
 [ScriptIgnore]
 public virtual List<Hit> Hits { get; set; }
}
公共类统计
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串说明{get;set;}
公共虚拟列表数量{get;set;}
[脚本忽略]
公共虚拟列表命中{get;set;}
}

很好的解决方案,适合我。然而,我仍然对循环引用(或依赖项-有什么区别…?)感到困惑。在我的例子中,有一个先决条件,例如,如果一个统计数据有3个数量,那么当一个HitComponent插入到一个数量时,其他2个数量也必须有1-1个HitComponents。这个前提条件出现在类/数据库表的设计中,这是一个好的实践吗?还是在程序逻辑中考虑这一规则更好,并且有一个没有循环引用的更干净的设计-例如,删除统计和命中之间的引用?