我正在基于NHibernate的winforms应用程序中进行一些批量插入操作。这对我很有帮助如果我可以在程序执行期间动态地将ID生成器类型从“guid.comb”更改为“分配”。在NHibernate类映射中动态更改ID生成器以“分配”
我碰到詹姆斯·科瓦奇博客文章Testing Immutable Entities with NHibernate
,他做了类似的事情时,他改变从一成不变到可变类,但我不能这个申请改变发电机类型。任何帮助,将不胜感激。
我正在基于NHibernate的winforms应用程序中进行一些批量插入操作。这对我很有帮助如果我可以在程序执行期间动态地将ID生成器类型从“guid.comb”更改为“分配”。在NHibernate类映射中动态更改ID生成器以“分配”
我碰到詹姆斯·科瓦奇博客文章Testing Immutable Entities with NHibernate
,他做了类似的事情时,他改变从一成不变到可变类,但我不能这个申请改变发电机类型。任何帮助,将不胜感激。
正如我在评论中链接到的问题的答案中所述,在创建SessionFactory后无法更改它。因此,唯一的选择是保留SessionFactory的第二个实例(最好也是一个Singleton)。这不必与第一次同时创建。您可以在需要时创建它,但由于创建过程非常昂贵,建议您创建一次并保存它。
但是,如果您真的只需要它在应用程序的运行时期间只发生一次或两次的批量插入操作,那么也可以在操作之后将其删除。
这是理论,现在到实际部分。简单的方法是获取Entity.hbm.xml文件的副本,您只需更改生成器属性即可。为了创建SessionFactory,你需要提供一个参数(也许是一个Enum),以便你可以决定使用哪些.hbm.xml文件以及忽略哪些文件。
我建议命名默认的hbm文件Entity.Default.hbm.xml和修改后的Entity.Special.hbm.xml。所有其他的HBM文件可以保留他们的名字。
这里是我用来创建SessionFacory的方法的修改版本。 (我把一个布尔值作为参数,在这里,但在我的代码使用枚举。)
private ISessionFactory BuildSessionFactory(bool useSpecialHbmFiles)
{
Configuration config = new Configuration();
config.SetProperty(NHibernate.Cfg.Environment.ConnectionProvider, "...");
config.SetProperty(NHibernate.Cfg.Environment.Dialect, "...");
config.SetProperty(NHibernate.Cfg.Environment.ConnectionDriver, "...");
config.SetProperty(NHibernate.Cfg.Environment.ConnectionString, "...");
config.SetProperty(NHibernate.Cfg.Environment.Isolation, "Serializable");
config.SetProperty(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, "...");
config.SetProperty(NHibernate.Cfg.Environment.ShowSql, "true");
config.SetProperty(NHibernate.Cfg.Environment.Hbm2ddlKeyWords, "none");
// filter hbm Files
// Set reference to entity assembly
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(MyEntity));
// get Resource-files
string[] resources = assembly.GetManifestResourceNames();
// scan through all the hbm files and filter them according to the parameter
foreach (string hbmFile in resources)
{
// This filtering here could probably be done simpler, but this is easy to understand
bool addFile = false;
// ignore any file that does not end with .hbm.xml
if (hbmFile.EndsWith(".hbm.xml"))
{
if (hbmFile.ToLower().EndsWith(".default.hbm.xml"))
{
if (!useSpecialHbmFiles)
{
// we want that file for this SessionFactory
addFile = true;
}
}
else if (hbmFile.ToLower().EndsWith(".special.hbm.xml"))
{
if (useSpecialHbmFiles)
{
// we want that file for this SessionFactory
addFile = true;
}
}
else
{
// neither default nor special -> we want that file no matter what
addFile = true;
}
if (addFile)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(assembly.GetManifestResourceStream(hbmFile)))
{
string resourceContent = sr.ReadToEnd();
config.AddXmlString(resourceContent);
}
}
}
}
// create Sessionfactory with the files we filtered
ISessionFactory sessionFactory = config.BuildSessionFactory();
return sessionFactory;
}
编辑:
如果你只是想在运行时修改的生成器类,你可以修改configuation构建SessionFactory的这样前:
// get the mapping's Key property
NHibernate.Mapping.SimpleValue keyValue =
config.GetClassMapping(typeof(MyEntity)).Key as NHibernate.Mapping.SimpleValue;
if (keyValue != null)
{
// set GeneratorStrategy (the same string you would put in generator class="..." in the hbm file)
keyValue.IdentifierGeneratorStrategy = "assigned";
}
现在,您可以将参数传递给您的CreateSessionFactory()方法和修改配置。您仍然需要第二个SessionFactory。你不能修改现有的。
编辑2(禁用多到一):
要为许多到一个属性禁用映射一个非空属性,尝试以下操作:
NHibernate.Mapping.PersistentClass mapping = config.GetClassMapping(typeof(MyEntity));
foreach (NHibernate.Mapping.Property prop in mapping.PropertyIterator)
{
if (prop.Value is NHibernate.Mapping.ManyToOne)
{
prop.IsOptional = true;
}
}
当然,这只有在DB中的外键列允许NULL值时才有效。
可能的[NHibernate - 如何动态切换ID生成器?](http://stackoverflow.com/q/5089066/634872) – 2011-03-18 13:45:34
嗨Florian,在你指的是,解决方案是切换到流利的NHibernate。如果无论如何,我想避免这种情况(必须重构所有映射) – zszep 2011-03-19 08:57:47