ICompositeUserType
インターフェイスの XML コメントは次のことを示しています。
This interface allows a custom type to define "properties".
--> These need not necessarily correspond to physical .NET style properties.
複数の列をリストにマップするような場合があります。
// Each column is mapped into this object
public class IdentifiedValue
{
public string Name;
public object Value;
}
public class CompanyContainer
{
public virtual int Id { get; set; }
public virtual IList<IdentifiedValue> Values { get; set; }
}
// The columns being mapped:
public class GeneratedColumns
{
public static string[] ColumnsInfo
{
get
{
return new[]
{
"CODE_TYPE",
"CODE_VALUE",
"CODE_DESC_NL",
"CODE_DESC_FR",
"CODE_DESC_EN"
};
}
}
}
ICompositeUserType の実装: (無関係なメソッドは省略)
public class IdentifiedValueMapper : ICompositeUserType
{
public string[] PropertyNames
{
get
{
var result = new List<string>();
foreach (var columnInfo in GeneratedColumns.ColumnsInfo)
{
result.Add(columnInfo);
}
return result.ToArray();
}
}
public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner)
{
if (dr == null)
{
return null;
}
var result = new List<IdentifiedValue>();
for (int i = 0; i < names.Length; i++)
{
var value = NHibernateUtil.String.NullSafeGet(dr, names[i], session, owner) as string;
result.Add(new IdentifiedValue()
{
Name = names[i],
Value = value
});
}
return result;
}
public IType[] PropertyTypes
{
get
{
var result = new List<IType>();
foreach (var columnInfo in GeneratedColumns.ColumnsInfo)
{
result.Add(NHibernateUtil.String);
}
return result.ToArray();
}
}
public Type ReturnedClass
{
get { return typeof(List<IdentifiedValue>); }
}
}
マッピング自体
public class CompanyContainerMap : ClassMap<CompanyContainer>
{
public CompanyContainerMap()
{
Table("S1073_CODE");
Id(x => x.Id).Column("CODE_ID");
var cols = Map(x => x.Values)
.CustomType<IdentifiedValueMapper>()
.Columns.Clear();
foreach (var col in GeneratedColumns.ColumnsInfo)
{
cols.Columns.Add(col);
}
}
}
失敗したテスト コード:
[TestMethod]
public void TestMethod1()
{
var factory = BuildSessionFactory();
using (var session = factory.OpenSession())
{
var query = session.QueryOver<CompanyContainer>();
query.Where(Restrictions.Eq("CODE_VALUE", "1"));
var result = query.List();
var blah = result;
}
}
クエリ実行時の例外:
could not resolve property: CODE_VALUE of: CompanyContainer
そのため、まだ存在しない CompanyContainer.CODE_VALUE にアクセスしようとしているようです。生成したいだけなので、なぜ.NETプロパティにアクセスしたいのかわかりませんWHERE CODE_VALUE='1'
。
Where 句なしで実行すると、正しく機能します。