NHibernateはインターセプターにマップされていない列を追加します
-
05-07-2019 - |
質問
NHibernateを使用してマップされたエンティティを保存しようとしていますが、基になるテーブルにNULLを許可しない列があり、ドメインオブジェクトにマップされていないため、データベースへの挿入が失敗します。マッピングされない理由は、問題の列がレガシーアプリケーションをサポートし、アプリケーションに関連性がないためです。したがって、レガシープロパティでエンティティを汚染したくないのです。
クラス内でプライベートフィールドを使用できることは知っていますが、それでも私には不快感を覚えます。 NHibernateインターセプターを使用してOnSave()メソッドをオーバーライドして追加できる読むエンティティが保存される直前の新しい列。 Nhibernate.type.ITypeのインスタンスをインターセプターのOnSaveのtypesパラメーターに追加する方法がわからないため、これは難しいことが判明しています。
私のエンティティはおおよそ次のようになります:
public class Client
{
public virtual int Id { get; set; }
public virtual int ParentId { get; set; }
public virtual string Name { get; set; }
public virtual string Phone { get; set; }
public virtual string Email { get; set; }
public virtual string Url { get; set; }
}
そしてインターセプター
public class ClientInterceptor : EmptyInterceptor
{
public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types)
{
if (entity is Client)
{
/*
manually add the COM_HOLD column to the Client entity
*/
List<string> pn_list = propertyNames.ToList();
pn_list.Add("COM_HOLD");
propertyNames = pn_list.ToArray();
List<Object> _state = state.ToList();
_state.Add(false);
state = _state.ToArray();
//somehow add an IType to types param ??
}
return base.OnSave(entity, id, state, propertyNames, types);
}
}
これを適切に行う方法についてのアイデアはありますか?
解決
実際にこれをやったことがないので確かに言うことはできません(Stefanのように、プライベートプロパティを追加することも好みます)が、 NHibernate.Type.BooleanType
types
配列へ?
List<IType> typeList = types.ToList();
typeList.Add(new BooleanType());
types = typesList.ToArray();
編集
はい、あなたは正しいようです。型には internal
コンストラクタがあります。掘り下げて TypeFactory
を見つけました:
アプリケーションは静的を使用する必要があります メソッドと定数 NHibernate.NHibernateUtilの場合 デフォルトのITypeで十分です。たとえば、TypeFactoryは 文字列の長さを255ではなく300にする必要がある場合に使用します。この時点で NHibernate.Stringは、正しいITypeを取得しません。代わりにTypeFactory.GetString(300)を使用して、 ITypeへの参照を保持するローカル変数。
だから、あなたが望むものは NHibernateUtil
のように見えます:
すべての範囲へのアクセスを提供します NHibernate組み込み型。私はタイプする インスタンスを使用して値をバインドできます パラメータを照会します。また、工場 新しいブロブとクローブ用。
typeList.Add(NHibernateUtil.Boolean);
他のヒント
個人的にはそれほど複雑にはしません。プライベートプロパティを追加し、デフォルト値を割り当てます-完了しました。データベースのデフォルト値を考慮することもできます。そうすれば、他に何もする必要はありません。
private virtual bool COM_HOLD
{
get { return false; }
set { /* make NH happy */ }
}
インターセプターを作成する前に、データベーストリガーを作成することを検討します。インターセプターを使用すると、「汚染」するためです。データアクセス層。不安定になる可能性があり 、奇妙な問題が発生する可能性があります。