C# 不带版本信息的Fluent nhibernate映射类型
有一个类具有类型属性C# 不带版本信息的Fluent nhibernate映射类型,c#,nhibernate,fluent-nhibernate,nhibernate-mapping,fluent-nhibernate-mapping,C#,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,Fluent Nhibernate Mapping,有一个类具有类型属性 [Serializable] public class MeasureTask { private Type _typeToStore; public MeasureTask() : this(null) {} public virtual Type TypeToStore { get { return _typeToStore; } set { _typeToStore= valu
[Serializable]
public class MeasureTask
{
private Type _typeToStore;
public MeasureTask()
: this(null)
{}
public virtual Type TypeToStore
{
get { return _typeToStore; }
set { _typeToStore= value; }
}
}
此类到MSSQL DB的FluentNHibernate映射
public class MeasureTaskMap : SubclassMap<MeasureTask>
{
public MeasureTaskMap()
{
Map(x => x.TypeToStore);
}
}
公共类MeasureTaskMap:子类映射
{
公共度量askmap()
{
Map(x=>x.TypeToStore);
}
}
默认情况下,此映射将类型的AssemblyQualifiedName
存储为数据库中的字符串。例如:
TopNamespace.SubNameSpace.MeasureTask,MyAssembly,版本=1.0.0.0,区域性=neutral,PublicKeyToken=b17a5c561934e089
现在,当程序集编译为更高版本时,例如
TopNamespace.SubNameSpace.MeasureTask,MyAssembly,版本=2.0.0.0,区域性=中性,PublicKeyToken=b17a5c561934e089
然后Nhibernate尝试从存储在数据库中的程序集Version=1.0.0.0
加载类型。但是当前类型已更改为Version=2.0.0.0
,这将导致TypeNotFoundException
现在,如何解决这个问题。我不想手动从AssemblyQualifiedName中删除版本信息,因为它会产生开销。有没有其他标准的方法可以做到这一点?因为,有许多这样的类需要映射,这正在成为一个突破性的问题。您必须手动进行映射,因为默认实现(NHibernate.Type.TypeType)没有用于映射的参数。使用约定应用的用户类型(ImmutableUserType)应该很方便
public class VersionAgnosticType : ImmutableUserType
{
public override object NullSafeGet(IDataReader rs, string[] names, object owner)
{
var typename = TypeNameParser.Parse((string)NHibernateUtil.String.Get(rs, names[0])));
return Type.GetType(typename.Type + ", " + new AssemblyName(typename.Assembly).Name);
}
public override void NullSafeSet(IDbCommand cmd, object value, int index)
{
var type = (Type)value;
NHibernateUtil.String.Set(cmd, type.FullName + "," + type.Assembly.GetName().Name, index);
}
public override Type ReturnedType
{
get { return typeof(Type); }
}
public override SqlType[] SqlTypes
{
get { return new[] { SqlTypeFactory.GetString(255) }; }
}
}
public class TypePropertyConvention : IPropertyConvention
{
public void Apply(IPropertyInstance instance)
{
if (instance.Type == typeof(Type))
instance.CustomType<VersionAgnosticType>();
}
}
public类versionAgonisticType:ImmutableUserType
{
公共重写对象NullSafeGet(IDataReader rs,字符串[]名称,对象所有者)
{
var typename=TypeNameParser.Parse((string)NHibernateUtil.string.Get(rs,names[0]);
返回Type.GetType(typename.Type+“,”+新程序集名称(typename.Assembly.Name);
}
public override void NullSafeSet(IDbCommand cmd,对象值,int索引)
{
变量类型=(类型)值;
NHibernateUtil.String.Set(cmd,type.FullName+”,“+type.Assembly.GetName().Name,index);
}
公共重写类型ReturnedType
{
获取{return typeof(Type);}
}
公共重写SqlType[]SqlTypes
{
获取{returnnew[]{SqlTypeFactory.GetString(255)};}
}
}
公共类类型PropertyConvention:IPropertyConvention
{
公共无效应用(IPropertyInstance实例)
{
if(instance.Type==typeof(Type))
CustomType();
}
}
它的用途是什么?我将TypePropertyConvention添加到AutoPersistenceModel中的约定列表中。我们应该为属性使用此类型而不是System.Type吗?那么我们如何映射属性呢?当然,VersionAgnosticType不能强制转换为System.Type。VersionAgnosticType是一个IUserType,负责将Type属性的值转换为数据库表示形式,而域模型对此没有任何连接/知识。该约定基本上是说“存储类型对象的所有属性都将由VersionAgnosticType序列化”,谢谢,它现在几乎可以工作了。我加了几张支票。因为有时NullSafeGet()的names[]参数将此wierd字符串“SourceType_80_0_”作为typeName,因此NHibernateUtil.string.Get()无法解析它并返回空字符串。这是一个问题吗?SourceType\u 80\u 0\u
是NHibernate为该列提供的别名,用于区分它,因为可能存在自联接,并且同一列返回两次。作为列的索引,它在结果集中应始终有效。如果从NHibernateUtil.string.Get
返回string.empty,则该列很可能包含一个空字符串。您可以执行rs[names[0]]
并查看原始返回值