我的应用程序同时支持Oracle和MS SQL数据库,与已实施了每一个稍微不同的模式。我碰到的一个问题是一类具有在MS SQL一个自动增加的主键,但甲骨文在手动插入的主键。
目前,两种不同的映射类是这样的:
甲骨文:
<类懒惰=假NAME =EntityPropertyName表=entity_property_name>
< ID名称=ID列=id类型=的Int32未保存值= - 1>
<生成器类=增量/>
< / ID>
<属性名=姓名一栏=名/>
MS SQL:
<类懒惰=假NAME =EntityPropertyName表=entity_property_name>
< ID名称=ID列=id类型=的Int32未保存值= - 1>
<生成器类=本土与GT;
< /发电机>
< / ID>
<属性名=姓名一栏=名/>
这还不是最糟糕的事情在世界上,因为我可以把他们分为不同的映射文件并加载正确的在运行时。
NHibernate.Cfg.Configuration CFG =新NHibernate.Cfg.Configuration();
如果(newDBType == CompanyName.AppName.Data.Enum.DatabaseType.MsSqlServer)
{
cfg.Properties [方言] =NHibernate.Dialect.MsSql2000Dialect;
cfg.Properties [connection.driver_class] =NHibernate.Driver.SqlClientDriver;
cfg.AddFile(数据类型\\ MSSQLTypes.hbm.xml);
}
其他
{
cfg.Properties [方言] =NHibernate.Dialect.Oracle9Dialect;
cfg.Properties [connection.driver_class] =NHibernate.Driver.OracleClientDriver;
cfg.AddFile(数据类型\\ OracleTypes.hbm.xml);
}
cfg.Properties [connection.provider] =NHibernate.Connection.DriverConnectionProvider;
cfg.Properties [connection.connection_string] =的connectionString;
cfg.AddAssembly(CompanyName.AppName.Data);
会话= cfg.BuildSessionFactory();
我不喜欢这一战略的事情是,虽然我现在已经在我的项目的bin目录中一些丑陋的XML文件,这需要在那里或应用程序将无法正常工作。这将是一个好多了,如果我可以嵌入不同的文件到资源就像我可以和我的主映射文件,而是选择是否加载每个文件或无法在运行时。
有没有办法做到这一点,或者以不同的方式来解决这个问题?
编辑: 谢谢你,克里斯蒂安!你没明白的问题,我只是不知道资源可NHibernate的加载这样。它的思考,我想这是有道理的AddAssembly方法,就必须有某种方式来列举并加载它找到的!
资源我的解决方案,结束了:
NHibernate.Cfg.Configuration CFG =新NHibernate.Cfg.Configuration();
如果(newDBType == CompanyName.AppName.Data.Enum.DatabaseType.MsSqlServer)
{
cfg.Properties [方言] =NHibernate.Dialect.MsSql2000Dialect;
cfg.Properties [connection.driver_class] =NHibernate.Driver.SqlClientDriver;
cfg.AddInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("CompanyName.AppName.Data.DataTypes.MSSQLTypes.hbm.xml"));
}
其他
{
cfg.Properties [方言] =NHibernate.Dialect.Oracle9Dialect;
cfg.Properties [connection.driver_class] =NHibernate.Driver.OracleClientDriver;
cfg.AddInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("CompanyName.AppName.Data.DataTypes.OracleTypes.hbm.xml"));
}
cfg.Properties [connection.provider] =NHibernate.Connection.DriverConnectionProvider;
cfg.Properties [connection.connection_string] =的connectionString;
cfg.AddInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("CompanyName.AppName.Data.DataTypes.Types.hbm.xml"));
会话= cfg.BuildSessionFactory();
解决方案
我可能会丢失你的要害。 NHibernate的是相当灵活的,你如何给它的映射文件。例如,
cfg.AddInputStream(assembly.GetManifestResourceStream("MyNamespace.MyEmbeddedresource.hbm.xml"));
或定制的XML字符串:
cfg.AddXml(myCustomBuildXmlString);
您也可以通过编程直接添加映射,但是这是一个有点棘手。
My application supports both Oracle and MS SQL databases, with slightly different schemas having been implemented for each. One issue I've run into is a class that has an auto-increment primary key under MS SQL, but a manually-inserted primary key under Oracle.
Right now, the two different mappings for the class look like this:
Oracle:
<class lazy="false" name="EntityPropertyName" table="entity_property_name" >
<id name="ID" column="id" type="Int32" unsaved-value="-1">
<generator class="increment" />
</id>
<property name="Name" column="name"/>
MS SQL:
<class lazy="false" name="EntityPropertyName" table="entity_property_name" >
<id name="ID" column="id" type="Int32" unsaved-value="-1">
<generator class="native">
</generator>
</id>
<property name="Name" column="name"/>
This isn't the worst thing in the world, because I can put them into different mapping files and load the correct one at runtime.
NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
if (newDBType == CompanyName.AppName.Data.Enum.DatabaseType.MsSqlServer)
{
cfg.Properties["dialect"] = "NHibernate.Dialect.MsSql2000Dialect";
cfg.Properties["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";
cfg.AddFile("DataTypes\\MSSQLTypes.hbm.xml");
}
else
{
cfg.Properties["dialect"] = "NHibernate.Dialect.Oracle9Dialect";
cfg.Properties["connection.driver_class"] = "NHibernate.Driver.OracleClientDriver";
cfg.AddFile("DataTypes\\OracleTypes.hbm.xml");
}
cfg.Properties["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider";
cfg.Properties["connection.connection_string"] = connectionString;
cfg.AddAssembly("CompanyName.AppName.Data");
Sessions = cfg.BuildSessionFactory();
The thing I dislike about this strategy though is that I now have some ugly XML files in my program's bin directory, which need to be there or the application won't work. It would be a lot better if I could embed the different files into the resource like I can with my main mapping file, but choose whether to load each file or not at runtime.
Is there any way to do this, or perhaps a different way to solve the problem?
Edit: Thank you, Cristian! You did understand the question, I was just unaware that resources could be loaded by NHibernate like that. Thinking on it, I suppose it makes sense for the AddAssembly method would have to have some way to enumerate and load the resources that it finds!
My solution ended up being:
NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
if (newDBType == CompanyName.AppName.Data.Enum.DatabaseType.MsSqlServer)
{
cfg.Properties["dialect"] = "NHibernate.Dialect.MsSql2000Dialect";
cfg.Properties["connection.driver_class"] = "NHibernate.Driver.SqlClientDriver";
cfg.AddInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("CompanyName.AppName.Data.DataTypes.MSSQLTypes.hbm.xml"));
}
else
{
cfg.Properties["dialect"] = "NHibernate.Dialect.Oracle9Dialect";
cfg.Properties["connection.driver_class"] = "NHibernate.Driver.OracleClientDriver";
cfg.AddInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("CompanyName.AppName.Data.DataTypes.OracleTypes.hbm.xml"));
}
cfg.Properties["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider";
cfg.Properties["connection.connection_string"] = connectionString;
cfg.AddInputStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("CompanyName.AppName.Data.DataTypes.Types.hbm.xml"));
Sessions = cfg.BuildSessionFactory();
解决方案
I might be missing your crucial point. NHibernate is quite flexible in how you can feed it the mapping files. e.g.
cfg.AddInputStream(assembly.GetManifestResourceStream("MyNamespace.MyEmbeddedresource.hbm.xml"));
or a custom built xml string:
cfg.AddXml(myCustomBuildXmlString);
You can also add mappings programmatically directly but that's a bit trickier.