2014-01-27 3 views
12

Я получаю прерывистую проблему с NHibernate, где он генерирует запрос для объекта, но заменяет один из столбцов столбцом из совершенно другого (и несвязанного) объекта.NHibernate - неправильные столбцы по запросам

Он заменяет только один столбец и обычно решается путем перезапуска приложения (хотя иногда это требует нескольких попыток).

  • ASP.NET приложений (.NET 4,0)
  • SessionFactory, созданный в Application_Start
  • NHibernate 3.3.1- Все отображения/конфигурации осуществляется с помощью карт с помощью кода
  • Использование NHibernate критериев

Любой вход на это был бы очень признателен!

Entity

public class LiquiditySourceItem : RunDataEntity, IEntity<int> 
    { 
     public virtual int Id { get; protected internal set; } 
     public virtual int IdentID { get; protected internal set; } 
     public virtual string Portfolio { get; protected internal set; } 
     public virtual string ProfitCentre { get; protected internal set; } 
     public virtual DateTime? MaturityDate { get; protected internal set; } 
     public virtual string Curr1 { get; protected internal set; } 
     public virtual string Curr2 { get; protected internal set; } 
     public virtual decimal Reval { get; protected internal set; } 
     public virtual string ContractType { get; protected internal set; } 
     public virtual string ContractType2 { get; protected internal set; } 
     public virtual string ContractCode { get; protected internal set; } 
     public virtual decimal AmountSignedTradeUnit { get; protected internal set; } 
     public virtual decimal Amount2Signed { get; protected internal set; } 
     public virtual decimal SpotDelta { get; protected internal set; } 
     public virtual string TradeRevalCurr { get; protected internal set; } 
    } 

Entity Mapping

public LiquiditySourceItemMap() 
{ 
    Id(x => x.Id, map => map.Column("RowId")); 
    Property(x => x.IdentID, map => map.Column("IdentID")); 
    Property(x => x.Portfolio, map => map.Column("Portfolio")); 
    Property(x => x.ProfitCentre, map => map.Column("ProfitCentre")); 
    Property(x => x.MaturityDate, map => map.Column("Con_Expiry")); 
    Property(x => x.BuySell, map => map.Column("BS")); 
    Property(x => x.Curr1, map => map.Column("Curr1")); 
    Property(x => x.Curr2, map => map.Column("Curr2")); 
    Property(x => x.Reval, map => map.Column("Reval")); 
    Property(x => x.ContractType, map => map.Column("ContractType")); 
    Property(x => x.ContractType2, map => map.Column("ContractType2")); 
    Property(x => x.ContractCode, map => map.Column("ContractCode")); 
    Property(x => x.AmountSignedTradeUnit, map => map.Column("AmountSignedTradeUnit")); 
    Property(x => x.Amount2Signed, map => map.Column("Amount2Signed")); 
    Property(x => x.ValSpot, map => map.Column("Val_Spot")); 
    Property(x => x.SpotDelta, map => map.Column("SpotDelta")); 
    Property(x => x.TradeRevalCurr, map => map.Column("Traderevalcurr")); 
    Property(x => x.SourceReport, map => map.Column("SourceReport")); 
    ManyToOne(x => x.RunContext, map => map.Column("RunContextID")); 
    Table("Staging.vw_Liquidity"); 
} 

Отчет Entity

public class BusinessBreakdownStandardPosition : ReportRunDataEntity, IEntity<long> 
    { 
     public virtual long Id { get; set; } 
     public virtual decimal FinalNettingAmountUSD { get; set; } 
     public virtual decimal InitialChargeAmountUSD { get; set; } 
     public virtual BusinessBreakdownInitialPrr InitialPrr { get; set; } 
     public virtual IEnumerable<FinalInstrumentPosition> FinalInstrumentPositions { get; set; } 
     public virtual decimal CreditEventPaymentUSD { get; set; } 
     public virtual decimal ValuationChangeIncreaseUSD { get; set; } 
     public virtual decimal ValuationChangeDecreaseUSD { get; set; } 
     public virtual string ReportKey { get; set; } 
     public virtual decimal USDCharge { get; set; } 
     public virtual decimal USDChargeICG { get; set; } 
     public virtual string InstrumentType { get; set; } 
} 

Report Entity Mapping

public class BusinessBreakdownStandardPositionMap : ClassMapping<BusinessBreakdownStandardPosition> 
    { 
     public BusinessBreakdownStandardPositionMap() 
     { 
      Id(x => x.Id, 
       m => 
        { 
         m.Column("BusinessBreakdownStandardPositionID"); 
         m.Generator(Generators.HighLow, 
            g => 
            g.Params(
             new 
              { 
               table = "dbo.HiValue", 
               max_lo = 10000, 
               Where = string.Format("EntityName = 'BusinessBreakdownStandardPosition'") 
              })); 
        }); 
      Property(x => x.FinalNettingAmountUSD, map => map.Column("FinalNettingAmountUSD")); 
      Property(x => x.InitialChargeAmountUSD, map => map.Column("InitialAmountUSD")); 
      Property(x => x.CreditEventPaymentUSD); 
      Property(x => x.ValuationChangeDecreaseUSD); 
      Property(x => x.ValuationChangeIncreaseUSD); 
      Property(x => x.USDCharge); 
      Property(x => x.USDChargeICG); 
      Property(x=>x.InstrumentType); 
      ManyToOne(p => p.RunContext, map => map.Column("ReportRunContextID")); 
      ManyToOne(p => p.InitialPrr, m => 
       { 
        m.Column("InitialPrrID"); 
        m.Cascade(Cascade.All); 
       }); 
      Property(x => x.ReportKey); 
      Bag(x => x.FinalInstrumentPositions, collectionMapping => 
       { 
        collectionMapping.Table("Reporting.BusinessBreakdownFinalInstrumentPositionStandardPositionMap"); 
        collectionMapping.Cascade(Cascade.All); 
        collectionMapping.Key(k => k.Column("StandardPositionID")); 
       }, mapping => mapping.ManyToMany(y => y.Column("FinalInstrumentPositionID"))); 
      Table("Reporting.BusinessBreakdownStandardPosition"); 
     } 
    } 

SQL запросов, генерируемых NHibernate

SELECT 
    this_.RowId AS RowId47_0_, 
    this_.IdentID AS IdentID47_0_, 
    this_.Portfolio AS Portfolio47_0_, 
    this_.ProfitCentre AS ProfitCe4_47_0_, 
    this_.Con_Expiry AS Con5_47_0_, 
    this_.BS AS BS47_0_, 
    this_.Curr1 AS Curr7_47_0_, 
    this_.Curr2 AS Curr8_47_0_, 
    this_.Reval AS Reval47_0_, 
    this_.ContractType AS Contrac10_47_0_, 
    this_.ContractType2 AS Contrac11_47_0_, 
    this_.ContractCode AS Contrac12_47_0_, 
    this_.AmountSignedTradeUnit AS AmountS13_47_0_, 
    this_.Amount2Signed AS Amount14_47_0_, 
    this_.Val_Spot AS Val15_47_0_, 
    this_.SpotDelta AS SpotDelta47_0_, 
    this_.InitialAmountUSD AS Initial17_47_0_, 
    this_.RunContextID AS RunCont18_47_0_, 
    this_.SourceReport AS Sou19_47_0_ 
FROM Staging.vw_Liquidity this_ 

Исключение

System.Data.SqlClient.SqlException (0x80131904): Invalid column name 'InitialAmountUSD'. 

Как вы можете видеть, NHibernate заменил столбец LiquiditySourceItem «Traderevalcurr 'с' InitialAmountUSD ', которые ngs для объекта BusinessBreakdownStandardPosition. Эти сущности не имеют никакой связи. В противном случае SQL точно так же, как и следовало ожидать (включая порядок столбцов).

Наблюдение

  • неверный столбец всегда действующий столбец в другой отображенной сущности
  • неправильный столбец заменит существующую один
  • Проблемы иногда ocurrs между другими субъектами. Опять же, нет никакой связи между этими

Любые мысли?

+1

очень тщательный вопрос! – XcisioN

+0

Эта проблема всегда затрагивает те же объекты и столбцы, или это широко распространенная проблема? Если первый, я бы ожидал некоторую случайную неправильную конфигурацию где-то ... – Alex

+0

Есть, по крайней мере, еще одна сущность, с которой это происходит. Опять же, это прерывисто, и я еще не смог воссоздать проблему последовательно. – tpither

ответ

3

я задал тот же вопрос о NHibernate пользователей Google Groups форуме, а кто-то думает, что они разработали основную причину (и также предложил решение):

https://groups.google.com/forum/#!topic/nhusers/BZoBoyWQEvs

Проблема кода находится в PropertyPath.Equals (PropertyPath), который пытается определить равенство, используя только хэш-код. Это отлично подходит для небольших базовых кодов, поскольку по умолчанию Object.GetHashCode() возвращает индекс последовательного объекта. Тем не менее, после сбора мусора эти индексы повторно используются, поскольку финализированные объекты удаляются, и создаются новые объекты ... что приводит к тому, что несколько объектов получают один и тот же хэш-код ... После того, как сбор мусора начинается, пути собственности имеют шанс поделиться тот же хэш-код, который означает, что они будут в конечном счете, перепутать их настройщик для сталкивающихся свойств, таким образом неправильных имен столбцов ...

Если вы хотите, чтобы исправить эту ошибку, вы можете исправить исходный код NH:

Если у вас есть собственная копия источника NH, вы можете исправить ошибку, изменив NHibernate/Mapping/ByCode/PropertyPath.cs строку # 66 от:

return hashCode == other.GetHashCode();

To:

return hashCode == other.GetHashCode() && ToString() == other.ToString();

Пожалуйста, проверьте Группу Google для получения полной информации о проблеме.

Смежные вопросы