単一の列にマッピングされたいくつかのプロパティを使用して、USERTYPEをクエリできますか?
-
27-10-2019 - |
質問
次のドメインモデルがあります。
public class Name
{
private readonly string fullName;
public Name(string fullName) { this.fullName = fullName }
public string FullName { get { return fullName; } }
public string FirstName { get { /* ... */ } }
public string MiddleNames { get { /* ... */ } }
public string LastName { get { /* ... */ } }
public static implicit operator Name(string name) { /* ... */ }
}
public class Person
{
public Name BirthName { get; set; }
public Name Pseudonym { get; set; }
}
実装しました IUserType
そのため、各名前をフルネームの単一のデータベース列にマップできます。
この作品のようなクエリ:
var people = session.QueryOver<Person>()
.Where(p => p.Name == "John Doe")
.List();
しかし、私はこのようにクエリすることはできません:
var people = session.QueryOver<Person>()
.Where(p => p.Name.LastName == "Doe")
.List();
これでnhibernateを機能させることはできますか?
解決
私はNhibernateユーザーではありませんが、シナリオに関するここにあるすべての情報を分析していますが、答えにはできないという強い感じがします。
そのクラスに含まれる値をDBの単一の値にマッピングします。
ピースのクエリを許可するには、名前クラスのこれらのサブ情報がすべて完全な値にどのように関連しているかを理解する必要があります。
それは、あなたが持っているカスタムC#コードが何をしているかを理解することを意味します。
更新1:
上記の回答は、それをすべて自動的に生成することと、そこで言及した正確なクエリを使用することです。
@CSが提案したような問題を確実に回避できます。つまり、必要なことを行うユーザー定義の関数を定義し、それをnhibernateでマッピングします。
少なくともそれはあなたが次のようなことをすることを許可します:
session.QueryOver<Person>()
.Where(p => session.PersonLastName(p) == "Doe")
.List();
別の方法は、あなたが望むものに翻訳される拡張法を定義し、この記事のように実装することです。 http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html
その場合、使用法は次のようになります。
session.QueryOver<Person>()
.Where(p=> p.Name.LastNameExt() == "Doe")// Ext just to avoid name collision
.List();
最後に、サブプロパティをそれぞれのユーザー定義関数にマッピングできるかどうかはわかりません。そうすれば、クエリは次のように変更されないようになります。
session.QueryOver<Person>()
.Where(p => p.Name.LastName == "Doe")
.List();
すべての場合において、データの連結から解析データに変更しているわけではありません。それが本当にあなたに何かを買っているかどうかを知っているのはあなただけです。
他のヒント
私はそれが可能だと信じていますが、物事のSQL側でいくつかの作業が必要になるでしょう。私がおそらく最初に試すことは、あなたの名前を分割し、必要な比較を行う何らかの種類のUDFを作成することです。その後、nhibernateを拡張してこのUDFにマッピングできます。 したほうがいい SQL、HQL、またはICRITERAベースであろうと、クエリからこの関数を呼び出すことができます。
フルネームに対してのみクエリすることができるのは、1つのデータベースフィールドにすぎないため、クエリすることができます。
FirstNameとLastNameが個別の列になるようにマップすると、それぞれにクエリができるはずですが、FullNameというプロパティをクエリするのが難しい場合があります。
計算された列を作成する必要があります。彼らは読み取り専用になりますが、あなたはそれらに対して照会することができます。見る ここ.
できることは、これらのオブジェクトに独自のリポジトリラッパーを実装し、HQLを使用してこれらのタイプの「部分的価値による検索」クエリを実行できるGetUsersbyLastName()などのメソッドを実装することです。
次のようなものは、適切な検索文字列に合格した場合、任意の部分的な値で検索できるようにする必要があります。
var hql = "select p from People p where lower(p.BirthName) like :searchText";
編集:
Queryから最後の名前を削除しました。これが機能する方法は、アンクルされた検索テキストを、生まれながらのフィールドの開始または終了のいずれかに使用することです。たとえば、スミスの姓を持っているすべての人を検索したい場合、
var hql = "select p from People p where lower(p.BirthName) like '% smith'";
そして、ファーストネームジョーの人の場合:
var hql = "select p from People p where lower(p.BirthName) like 'joe %'";