模型关系:定义模型中关系的效率

时间:2017-09-29 18:31:21

标签: c# asp.net asp.net-mvc model asp.net-mvc-5

我想,这是一个高级别的问题,对于学者来说比挖掘者更多。

问题1:

当定义与另一个模型的外来关系时,例如,一对多关系,通常按以下方式定义:

public virtual ICollection<OtherModel> OtherModel { get; set; }

但是,我也看到它以下列方式定义:

private ICollection<OtherModel> _otherModel;
public virtual ICollection<OtherModel> OtherModel {
  get { return _otherModel ?? ( _otherModel = new List<OtherModel>() ); }
  set { _otherModel = value }
}

这对我有意义:如果没有从OtherModel引用此模型的条目(空值),则null-coalescing运算符确保创建一个空的,空的OtherModel集合。据我所知,这是一项安全措施。

但是,上述情况的演变似乎是这样的:

public class ThisModel {
  // Assorted model items

  public virtual ICollection<OtherModel> OtherModel { get; set; }

  public ThisModel(){
    OtherModel = new List<OtherModel>();
  }
}

不幸的是,我没有看到这两者是如何相同的。当OtherModel未引用ThisModel中的任何内容时,上面的第二个代码块清楚地使用空合并运算符来调用空白列表 ONLY ;当结果列表无论如何都是null。

当我阅读第三个代码块时,我将其解释为每次 OtherModel被调用时创建的ThisModel 的列表。

我希望有人可以就两者之间的任何差异给我一些澄清。

问题2:

在硬币的另一面,我们需要OtherModel中的条目。通常我们在OtherModel中构建反向关系,如下所示:

public virtual ThisModel ThisModel { get; set; }

但是我也看到它以下列方式定义:

public class OtherModel {
  // Various model stuff

  private ThisModel _thisModel;
  public virtual ThisModel ThisModel {
    get { return _thisModel; }
    set {
      if (value == null) throw new ArgumentNullException(nameof(value));
      _thisModel= value;
      ThisModelId = value.ThisModelId;
    }
  }
}

关键是,因为OtherModel具有必需的外键,如果该外键最终强制馈送空条目,则if语句显式抛出空异常。我喜欢这个。它确保对于所需的外键,不能使用或不能引入空值。它确保在CRUD操作中任何数据到达数据库之前很久就完成任何此类拒绝,并且在业务逻辑(堆栈中较高的位置,使用View模型)意外未扩展以涵盖该问题时充当备份。

在这种情况下,我的问题是如何将其浓缩为更高效的东西。

1 个答案:

答案 0 :(得分:2)

你是对的。它们是不同的,构造函数版本实际上是反模式。在构造函数中,无论列表是否具有值,您都在初始化空列表。例如,如果EF要初始化列表确实具有值的实例,则首先将该值设置为空列表,然后将其再次设置为EF应包含的列表。当然,简单地创建一个空列表并不是 效率低下,但是你仍然在为不需要的操作消耗一些RAM和CPU。

自定义getter和setter版本是lazy-set,因此仅当值为null时才会初始化空列表,这意味着不会浪费资源。再说一遍,这不是一个巨大的交易,但是这样一点点效率低下的问题最终可能会导致真正的问题(比如一千次削减死亡)。

但是,为了进一步增加皱纹:在C#6.0中,您实际上可以提供默认值而不使用自定义getter和setter。所以以下是最佳方式:

public virtual ICollection<OtherModel> OtherModel { get; set; } = new List<OtherModel>();

它的工作方式与自定义getter / setter版本完全相同,只是没有完全没法。