2011-04-04 28 views
1

我正在處理的應用程序需要支持3個數據庫。 Sybase,SQL和Oracle。讓2個不同的映射文件在同一個域中工作

現在我們對Oracle有一個問題。至於oracle,我們使用序列作爲id生成器,對於Sybase和Oracle,我們使用自己的實現來生成一個ID。

我們有一個由雙主鍵組成的表的問題。我的映射文件由一個composite-id組成。但是在複合標識中,您無法使用生成的值。對於Oracle和Sybase,這是沒有問題的,因爲我手動創建新的ID。對於Oracle,但我確實有問題,因爲需要使用序列。

所以我在做的是創建第二個特定於Oracle的映射文件,該文件只使用1個字段作爲PK。我的查詢將不會是正確的,但我看不出有任何其他選項,這樣做..

所以我有2個映射文件:

Sybase和SQL:

<?xml version="1.0" encoding="utf-8"?> 
<hibernate-mapping default-cascade="none" xmlns="urn:nhibernate-mapping-2.2" 
    namespace="VS3.Domain.Address" assembly="VS3.Domain"> 

<class name="Top_Address" table="TOP_ADDRESS"> 
<composite-id name="ID" class="IDComposite_TopAddress"> 
    <key-property name="TnrAddress" column="TNR_ADDRESS" type="Int32"/> 
    <key-many-to-one name="TopIdentity" class="Top_Identity" column="TNR_ID"/> 
</composite-id> 

<property name="nmAddress" column="NM_ADDRESS" type="String" not-null="true"/> 
<property name="dPosx" column="D_POSX" type="Decimal" not-null="false"/> 
<property name="dPosy" column="D_POSY" type="Decimal" not-null="false"/> 

<property name="nmStreetAdd" column="NM_STREET_ADD" type="String" not-null="false"/> 
<property name="nmStreetAdd2" column="NM_STREET_ADD2" type="String" not-null="false"/> 
<property name="nmStreetAdd3" column="NM_STREET_ADD3" type="String" not-null="false"/> 

<!-- Added By Transics --> 
<property name="HouseNumber" column="CNR_HOUSE_ADD" type="String" not-null="false" /> 
<property name="BusNumber" column="CNR_BUS_ADD" type="String" not-null="false" /> 
<property name="PostalCode" column="CNR_ZIP" type="String" not-null="false" /> 
<property name="City" column="NM_ZIP" type="String" not-null="false" /> 
<property name="Country" column="COD_COUNTRY" type="String" not-null="false" /> 
<property name="Email" column="CNR_EMAIL_ADD" type="String" not-null="false" /> 
<property name="Phone" column="CNR_PHONE_ADD" type="String" not-null="false" /> 
<property name="CellPhone" column="CNR_GSM_ADD" type="String" not-null="false" /> 
<property name="NmAddress2" column="NM_ADDRESS2" type="String" not-null="false" /> 

<property name="Active" column="BOL_ACTIVE_ADD" type="Int32" not-null="false" /> 
<property name="Language" column="COD_LANG" type="String" not-null="false" /> 
<property name="AmFrom" column="T_TRB_AM_FROM" type="DateTime" not-null="false" /> 
<property name="AmUntil" column="T_TRB_AM_UNTIL" type="DateTime" not-null="false" /> 
<property name="PmFrom" column="T_TRB_PM_FROM" type="DateTime" not-null="false" /> 
<property name="PmUntil" column="T_TRB_PM_UNTIL" type="DateTime" not-null="false" /> 
<property name="Remark" column="DES_TRB_REMARK" type="String" not-null="false" /> 
<property name="ExtraInformation" column="TXT_ADDRESS" type="String" not-null="false" /> 
<property name="AddressType" column ="COD_ADDRESSTYPE" type="Char" not-null="false" /> 
<property name="AddressOrPlace" column ="COD_TRB_ADDRESSTYPE" type="String" not-null="false" /> 

</class> 
</hibernate-mapping> 

甲骨文:

<?xml version="1.0" encoding="utf-8"?> 
<hibernate-mapping default-cascade="none" xmlns="urn:nhibernate-mapping-2.2" 
    namespace="VS3.Domain.Address" assembly="VS3.Domain"> 

<class name="Top_Address_Oracle" table="TOP_ADDRESS"> 
<id name="TnrAddress" column="TNR_ADDRESS" type="Int32"> 
    <generator class="sequence" /> 
</id> 

<property name="nmAddress" column="NM_ADDRESS" type="String" not-null="true"/> 
<property name="dPosx" column="D_POSX" type="Decimal" not-null="false"/> 
<property name="dPosy" column="D_POSY" type="Decimal" not-null="false"/> 

<property name="nmStreetAdd" column="NM_STREET_ADD" type="String" not-null="false"/> 
<property name="nmStreetAdd2" column="NM_STREET_ADD2" type="String" not-null="false"/> 
<property name="nmStreetAdd3" column="NM_STREET_ADD3" type="String" not-null="false"/> 
<property name="HouseNumber" column="CNR_HOUSE_ADD" type="String" not-null="false" /> 
<property name="BusNumber" column="CNR_BUS_ADD" type="String" not-null="false" /> 
<property name="PostalCode" column="CNR_ZIP" type="String" not-null="false" /> 
<property name="City" column="NM_ZIP" type="String" not-null="false" /> 
<property name="Country" column="COD_COUNTRY" type="String" not-null="false" /> 
<property name="Email" column="CNR_EMAIL_ADD" type="String" not-null="false" /> 
<property name="Phone" column="CNR_PHONE_ADD" type="String" not-null="false" /> 
<property name="CellPhone" column="CNR_GSM_ADD" type="String" not-null="false" /> 
<property name="NmAddress2" column="NM_ADDRESS2" type="String" not-null="false" /> 

<property name="Active" column="BOL_ACTIVE_ADD" type="Int32" not-null="false" /> 
<property name="Language" column="COD_LANG" type="String" not-null="false" /> 
<property name="AmFrom" column="T_TRB_AM_FROM" type="DateTime" not-null="false" /> 
<property name="AmUntil" column="T_TRB_AM_UNTIL" type="DateTime" not-null="false" /> 
<property name="PmFrom" column="T_TRB_PM_FROM" type="DateTime" not-null="false" /> 
<property name="PmUntil" column="T_TRB_PM_UNTIL" type="DateTime" not-null="false" /> 
<property name="Remark" column="DES_TRB_REMARK" type="String" not-null="false" /> 
<property name="ExtraInformation" column="TXT_ADDRESS" type="String" not-null="false" /> 
<property name="AddressType" column ="COD_ADDRESSTYPE" type="Char" not-null="false" /> 
<property name="AddressOrPlace" column ="COD_TRB_ADDRESSTYPE" type="String" not-null="false" /> 

<many-to-one name="Identity" class="Identity" column="TNR_ID" not-null="true"/> 
</class> 
</hibernate-mapping> 

有沒有什麼辦法可以確保這些映射文件使用相同的Domain類?或者我也需要創建一個新域名(就像我目前那樣)。

但這不是一個真正的選擇。會很多工作。

有沒有人有解決方案?

回答

0

您可以爲同一個域類創建兩個映射文件 - 如果您在執行代碼的過程中只需要一個映射文件(我認爲這樣做,因爲使用相同的表和兩個不同的數據庫同時工作是一場噩夢;域類)。在創建SessionFactory之前,您可以過濾hbm文件,並根據參數只採取那些您想要的。

您需要爲Oracle映射文件,另一個用於休息,例如MyEntity.oracle.hbm.xmlMyEntity.default.hbm.xml。對於那些在兩種情況下都完全相同的類,您只需保留它們,例如MyCommonEntity.hbm.xml

下面是我在我們的項目中使用的代碼稍加修改的例子。(我在另一個問題發佈的另一個版本在這裏SO:Dynamically change the id generator to 「assigned」 in NHibernate class mapping

private ISessionFactory BuildSessionFactory(bool useOracleMapping) 
{ 
    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 (!useOracleMapping) 
       { 
        // we want that file for this SessionFactory 
        addFile = true; 
       } 
      } 
      else if (hbmFile.ToLower().EndsWith(".oracle.hbm.xml")) 
      { 
       if (useOracleMapping) 
       { 
        // we want that file for this SessionFactory 
        addFile = true; 
       } 
      } 
      else 
      { 
       // neither default nor oracle -> 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; 
} 

編輯:

假設你可以隨時獲取知識無論你是在Oracle或其他方式,我將包裹GetTop_AddressById()方法和做類似如下:

public Top_Address GetTop_AddressById(IDComposite_TopAddress id) 
{ 
    if (!oracle) 
    { 
     return session.CreateCriteria(DB, typeof(Top_Address)) 
      .Add(Restrictions.Eq("ID.TnrAddress", addressID)) 
      .Add(Restrictions.Eq("ID.TopIdentity.tnrId", tnrID)) 
      .Add(Restrictions.Eq("AddressType", 'R')) .UniqueResult<Top_Address>(); 
    } 
    else 
    { 
     return session.CreateCriteria(DB, typeof(Top_Address)) 
      .Add(Restrictions.Eq("TnrAddress", addressID)) 
      .Add(Restrictions.Eq("AddressType", 'R')) .UniqueResult<Top_Address>(); 
    } 
} 

這可能不漂亮,但具有同樣的目的兩類更糟糕的是,我想。對於使用該ID的所有CRUD操作,您將需要這樣的包裝。當然,您還需要在您的域類中擁有TnrAddress屬性。

+0

謝謝:)這已經有點幫助我了。在我的域中(正如你可以在我的映射文件中看到的那樣)我爲PK創建了一個類。我的oracle映射文件不是這種情況。 我正在使用它來檢索我的服務中的某些值等。例如:CreateCriteria(DB,typeof(Top_Address)) .Add(Expression.Eq(「ID.TnrAddress」,addressID)) .Add(Expression.Eq(「ID.TopIdentity.tnrId」,tnrID)) 。 Add(Expression.Eq(「AddressType」,'R')) .UniqueResult (); 這樣做,如果我這樣做,而不改變我的域名,只有映射? – JeremyVm 2011-04-04 13:16:37

+0

@JeremyVm看到我的編輯來解決你的問題。 – 2011-04-04 14:45:27

+0

謝謝!也是我想要做的,但希望有一個更好的解決方案.. – JeremyVm 2011-04-04 15:21:17

0

我建議你不要分叉映射,而應該: 通過映射元數據反序列化,在創建SessionFacorty之前,添加所需的修改。我不能給你的代碼,但在這裏,你可以抓住的想法:http://fabiomaulo.blogspot.com/2010/01/map-nhibernate-using-your-api.html

或者

創建自定義ID生成,這裏內把手tghe兩個關鍵系統之間的區別: http://nhforge.org/wikis/howtonh/creating-a-custom-id-generator-for-nhibernate.aspx

+0

嗨,謝謝你回答:)我將無法使用第一種方法,因爲不是整個應用程序使用Nhibernate。我們只將它用於應用程序的一部分。 創建自定義ID生成器也無法工作,因爲在複合ID中,我無法添加生成的值。 – JeremyVm 2011-04-04 12:11:52

相關問題