コア アセンブリでこの単純なドメインを想定します。
public class Country
{
protected ICollection<Province> _provinces = null;
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual string IsoCode2 { get; set; }
public virtual string IsoCode3 { get; set; }
public virtual int IsoCodeNumeric { get; set; }
public virtual ICollection<Province> Provinces
{
get { return _provinces ?? (_provinces = new List<Province>()); }
set { _provinces = value; }
}
}
public class Province
{
public virtual int Id { get; protected set; }
public virtual Country Country { get; set; }
public virtual string Name { get; set; }
public virtual string Abbreviation { get; set; }
}
私のプレゼンテーション レイヤーのビュー モデルはほぼ同じです。
public class CountryModel
{
public int Id { get; set; }
public string Name { get; set; }
public string IsoCode2 { get; set; }
public string IsoCode3 { get; set; }
public int IsoCodeNumeric { get; set; }
public int NumberOfProvinces { get; set; }
}
public class ProvinceModel
{
public int Id { get; set; }
public int CountryId { get; set; }
public string Name { get; set; }
public string Abbreviation { get; set; }
}
ドメインオブジェクト/ビューモデル間で前後にマッピングするためのいくつかの拡張メソッドを作成しています:
public static class Extensions
{
public static Country ToEntity(this CountryModel model, Country entity = null)
{
if (entity == null)
entity = new Country();
entity.Name = model.Name;
entity.IsoCode2 = model.IsoCode2;
entity.IsoCode3 = model.IsoCode3;
entity.IsoCodeNumeric = model.IsoCodeNumeric;
entity.AddressFormat = model.AddressFormat;
entity.CanBillTo = model.CanBillTo;
entity.CanShipTo = model.CanShipTo;
entity.IsPublished = model.IsPublished;
return entity;
}
public static CountryModel ToModel(this Country entity, bool includeProvinceCount = false, CountryModel model = null)
{
if (model == null)
model = new CountryModel();
model.Id = entity.Id;
model.Name = entity.Name;
model.IsoCode2 = entity.IsoCode2;
model.IsoCode3 = entity.IsoCode3;
model.IsoCodeNumeric = entity.IsoCodeNumeric;
model.AddressFormat = entity.AddressFormat;
model.CanBillTo = entity.CanBillTo;
model.CanShipTo = entity.CanShipTo;
model.IsPublished = entity.IsPublished;
if (includeProvinceCount)
model.NumberOfProvinces = entity.Provinces.Count;
return model;
}
public static Province ToEntity(this ProvinceModel model, Province entity = null)
{
if (entity == null)
entity = new Province();
//entity.Country = LoadCountryById(model.CountryId); ???? <-- HERE
entity.Name = model.Name;
entity.Abbreviation = model.Abbreviation;
entity.CanBillTo = model.CanBillTo;
entity.CanShipTo = model.CanShipTo;
entity.IsPublished = model.IsPublished;
return entity;
}
public static ProvinceModel ToModel(this Province entity, ProvinceModel model)
{
if (model == null)
model = new ProvinceModel();
model.Id = entity.Id;
model.CountryId = entity.Country.Id;
model.Name = entity.Name;
model.Abbreviation = entity.Abbreviation;
model.CanBillTo = entity.CanBillTo;
model.CanShipTo = entity.CanShipTo;
model.IsPublished = entity.IsPublished;
return model;
}
}
Entity Framework では、Province ドメイン オブジェクトに Country プロパティと対応する CountryId プロパティの両方が含まれていました。CountryId を設定するだけで国を割り当てることができます。
NHibernate では、ドメイン作成時に外部キーの id は不要です。では、ProvinceModel CountryId を Country オブジェクトにマップするにはどうすればよいでしょうか。
物事をインターフェースに抽象化し、依存性注入を使用するために、あらゆる種類の手順を実行しました。マッピング拡張機能内からサービス ロケーターを使用して検索する必要がありますか? マッピング拡張の外で国を検索し、拡張メソッドのパラメーターとしてそれを要求する必要がありますか? このシナリオを処理するための推奨される方法は何ですか?
次に、NHibernate では、関連付けを維持するためにヘルパー関数をドメイン オブジェクトに追加することを推奨しています (肯定的ではありませんが、EF はこれを「自動的に」処理すると思います)。たとえば、SetCountry
Province にメソッドを追加し、 CountryAddProvince
にメソッドを追加します。RemoveProvince
これはパフォーマンスに影響しませんか? 州 (関連付けが管理されている場所) に単に国を設定する代わりに、新しい国の州のリスト全体が読み込まれ、コレクションに追加する前にリストに既に存在するかどうかが確認されます。 old Country の Provinces が読み込まれ、その州をコレクションから削除する必要があるかどうかが確認されます。