代码之家  ›  专栏  ›  技术社区  ›  Csati

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

  •  2
  • Csati  · 技术社区  · 11 年前

    在没有循环引用的情况下,有更好的设计吗?这是个问题吗? 课程:

    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; }
    }
    

    Class diagram Stat是用来统计某件事的,例如举重之类的训练。数量可以是可以用一个数字来衡量的东西,例如所用杠铃的重量(以千克为单位,单位存储在unit类中)或重复次数。在这种情况下,Stat(举重)有两个数量(重量,重复次数)。命中是Stat的一个项目(一次举重训练)。命中组件属于命中,它包含一个数量的数量。每一次命中都必须包含与命中统计数一样多的命中分量。(例如,每个“举重”统计的命中率都必须包含两个命中率分量,一个用于“重量”数量,一个表示“重复次数”数量。我怀疑,也许这个先决条件会导致一些问题…)

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

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

    1 回复  |  直到 6 年前
        1
  •  1
  •   Travis J    11 年前

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

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

    根据序列化程序的不同,忽略导航财产的操作将有所不同。使用Json(var)时使用的vanilla序列化程序(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; }
    }