我有一个带有 NHibernate 的自定义用户类型,并且自定义类型可以很好地保存和更新。QueryOver
但是,在此自定义用户类型上使用时会发生错误。我收到错误消息:could not resolve property: SpecialType.Code of: NHibernateComplexIUserTypeExample.Person
。
我知道我可以使用 Component() 而不是 Map() 将 SpecialType 类与自定义类型进行映射,但是在此示例之外还有其他一些考虑因素会使其不合适。如果可能的话,我想解决这个问题,同时将其保留为 IUserType。
这是我可能导致此错误的示例代码。
错误发生在Program.cs
与QueryOver<>
.
个人.cs
public class Person
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual SpecialType SpecialType { get; set; }
public Person()
{
}
}
人物地图.cs
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.Id);
Map(x => x.Name).Not.Nullable();
Map(x => x.SpecialType)
.CustomType<SpecialTypeUserType>()
.Not.Nullable()
.Column("SpecialType_Code");
}
}
程序.cs
class Program
{
static void Main(string[] args)
{
// create db session
var sessionFactory = Program.CreateSessionFactory();
var session = sessionFactory.OpenSession();
// query db using complex iusertype
var results = session.QueryOver<Person>().Where(x => x.SpecialType.Code == "1").List();
if (results != null)
{
foreach (var result in results)
{
Console.WriteLine("Person {0} has code {1}.", result.Name, result.SpecialType.Code);
}
}
}
public static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(
MsSqlConfiguration
.MsSql2008
.ConnectionString("..."))
.Mappings(
m =>
{
m.FluentMappings.AddFromAssemblyOf<Person>();
})
.BuildSessionFactory();
}
}
SpecialTypeUserType.cs
public class SpecialTypeUserType : global::NHibernate.UserTypes.IUserType
{
#region IUserType Members
public object Assemble(object cached, object owner)
{
// used for caching, as our object is immutable we can just return it as is
return cached;
}
public object DeepCopy(object value)
{
//? should we implement deep copy for this?
return value;
}
public object Disassemble(object value)
{
// used for caching, as our object is immutable we can just return it as is
return value;
}
public new bool Equals(object x, object y)
{
// implements equals itself so we use this implementation
if (x == null)
{
return false;
}
else
{
return x.Equals(y);
}
}
public int GetHashCode(object x)
{
if (x == null)
{
throw new ArgumentNullException("x");
}
// object itself implements GetHashCode so we use that
return x.GetHashCode();
}
public bool IsMutable
{
get
{
return false;
}
}
public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
{
if (names == null)
{
throw new ArgumentNullException("names");
}
// we get the string from the database using the NullSafeGet used to get strings
string codeString = (string)global::NHibernate.NHibernateUtil.String.NullSafeGet(rs, names[0]);
SpecialType newSpecialType = new SpecialType(codeString, "Test...");
return newSpecialType;
}
public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)
{
// set the value using the NullSafeSet implementation for string from NHibernateUtil
if (value == null)
{
global::NHibernate.NHibernateUtil.String.NullSafeSet(cmd, null, index);
return;
}
value = ((SpecialType)value).Code;
global::NHibernate.NHibernateUtil.String.NullSafeSet(cmd, value, index);
}
public object Replace(object original, object target, object owner)
{
// as our object is immutable we can just return the original
return original;
}
public Type ReturnedType
{
get
{
return typeof(SpecialType);
}
}
public NHibernate.SqlTypes.SqlType[] SqlTypes
{
get
{
// we store our SpecialType.Code in a single column in the database that can contain a string
global::NHibernate.SqlTypes.SqlType[] types = new global::NHibernate.SqlTypes.SqlType[1];
types[0] = new global::NHibernate.SqlTypes.SqlType(System.Data.DbType.String);
return types;
}
}
#endregion
}
特殊类型.cs
public class SpecialType
{
public string Code { get; private set; }
public string Description { get; private set; }
public SpecialType(string code, string description)
{
this.Code = code;
this.Description = description;
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
SpecialType type = obj as SpecialType;
if (type == null)
{
return false;
}
if (object.ReferenceEquals(this, type))
{
return true;
}
if (type.Code == null && this.Code != null)
{
return false;
}
else if (type.Code != null && this.Code == null)
{
return false;
}
else if (type.Code != null && this.Code != null)
{
if (!type.Code.Equals(this.Code, StringComparison.OrdinalIgnoreCase))
{
return false;
}
}
return true;
}
public override int GetHashCode()
{
return this.Code.GetHashCode();
}
}
数据库表定义
CREATE TABLE [dbo].[Person](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](255) NOT NULL,
[SpecialType_Code] [nvarchar](255) NOT NULL,
PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]