我正在基於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