Существует класс с свойством Type,
[Serializable]
public class MeasureTask
{
private Type _typeToStore;
public MeasureTask()
: this(null)
{}
public virtual Type TypeToStore
{
get { return _typeToStore; }
set { _typeToStore= value; }
}
}
FluentNHibernate для этого класса в MSSQL DB.
public class MeasureTaskMap : SubclassMap<MeasureTask>
{
public MeasureTaskMap()
{
Map(x => x.TypeToStore);
}
}
По умолчанию это сопоставление хранит AssemblyQualifiedName
Type
в виде string
в db. Например:
TopNamespace.SubNameSpace.MeasureTask, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089
Теперь, когда сборка скомпилирована в более высокую версию, например,
TopNamespace.SubNameSpace.MeasureTask, MyAssembly, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089
Затем Nhibernate пытается загрузить Type из сборки 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>();
}
}