2

Я использую таблицу для каждого типа (TPT) сделать наследование в NHibernate v3.3.1.4000. Я понял, что любые отношения SQL для SubClass «один ко многим» ошибочны.Nhibernate SubClass отношения генерируя неправильный SQL

Класс:

public class Repasse : Colaboracao 
{ 
    public virtual string Descricao { get; set; } 
    public virtual Decimal ValorRepasse { get; set; } 
    public virtual DateTime DataInicio { get; set; } 
    public virtual DateTime DataTermino { get; set; } 

    [XmlIgnore] 
    public virtual Usuario UsuarioExecucao { get; set; } 
    [XmlIgnore] 
    public virtual Usuario UsuarioMonitoramento { get; set; } 
    [XmlIgnore] 
    public virtual IList<RepasseRecebido> RepassesRecebidos { get; set; } 
    [XmlIgnore] 
    public virtual IList<RepasseProduto> Produtos { get; set; } 

    public Repasse() 
    { 
     RepassesRecebidos = new List<RepasseRecebido>(); 
     Produtos = new List<RepasseProduto>(); 
     UsuarioExecucao = new Usuario(); 
     UsuarioMonitoramento = new Usuario(); 
    } 
} 

public class RepasseRecebido : Entidade 
{ 
    public virtual string NumNotaAtorizacao { get; set; } 
    public virtual Decimal ValorTaxaCambio { get; set; } 
    public virtual DateTime DataRecebimento { get; set; } 
    public virtual Decimal ValorRecebido { get; set; } 
    public virtual string Observacao { get; set; } 

    [XmlIgnore] 
    public virtual Repasse Repasse { get; set; } 

    [XmlIgnore] 
    public virtual List<Download> Downloads { get; set; } 

    public RepasseRecebido() 
    { 
     Repasse = new Repasse(); 
     Downloads = new List<Download>(); 
    } 
} 

public class RepasseProduto : Entidade 
{ 
    public virtual int QtdProduto { get; set; } 
    public virtual DateTime DataInicio { get; set; } 
    public virtual DateTime DataTermino { get; set; } 
    public virtual int QtdBeneficiado { get; set; } 
    public virtual PublicoBeneficiado PublicoBeneficiado { get; set; } 

    [XmlIgnore] 
    public virtual Produto Produto { get; set; } 
    [XmlIgnore] 
    public virtual Repasse Repasse { get; set; } 
    [XmlIgnore] 
    public virtual IList<RepasseProdutoAtividade> Atividades { get; set; } 

    public RepasseProduto() 
    { 
     Produto = new Produto(); 
     Repasse = new Repasse(); 
     Atividades = new List<RepasseProdutoAtividade>(); 
    } 
} 

public class RepasseProdutoAtividade : Entidade 
{ 
    public virtual DateTime DataInicio { get; set; } 
    public virtual DateTime DataTermino { get; set; } 
    public virtual string Descricao { get; set; } 

    [XmlIgnore] 
    public virtual RepasseProduto RepasseProduto { get; set; } 

    public RepasseProdutoAtividade() 
    { 
     RepasseProduto = new RepasseProduto(); 
    } 
} 

Карта:

public class RepasseMap : SubclassMap<Repasse> 
{ 
    public RepasseMap() 
    { 
     Schema(ConfigInstances.ObterSchema("Sigma")); 
     Table("tblRepasse"); 
     LazyLoad(); 

     KeyColumn("cmpIdRepasse"); 

     Map(x => x.Descricao).Column("cmpDcDescricao"); 
     Map(x => x.ValorRepasse).Column("cmpVlValorRepasse").Not.Nullable(); 
     Map(x => x.DataInicio).Column("cmpDtDataInicio").Not.Nullable(); 
     Map(x => x.DataTermino).Column("cmpDtDataTermino").Not.Nullable(); 

     References(x => x.UsuarioExecucao).Column("cmpIdUsuarioExecucao"); 
     References(x => x.UsuarioMonitoramento).Column("cmpIdUsuarioMonitoramento"); 

     HasMany(x => x.RepassesRecebidos).AsBag().LazyLoad(); 
     HasMany(x => x.Produtos).KeyColumn("cmpIdRepasseProduto").AsBag().LazyLoad(); 
    } 

    public class RepasseRecebidoMap : ClassMap<RepasseRecebido> 
    { 
     public RepasseRecebidoMap() 
     { 
      Schema(ConfigInstances.ObterSchema("Sigma")); 
      Table("tblRecursoRepasse"); 
      LazyLoad(); 

      Id(x => x.Id).GeneratedBy.Identity().Column("cmpIdRecursoRepasse"); 

      Map(x => x.NumNotaAtorizacao).Column("cmpNuAutorizacaoNota").Not.Nullable(); 
      Map(x => x.DataRecebimento).Column("cmpDtDataRecebimento").Not.Nullable(); 
      Map(x => x.ValorRecebido).Column("cmpVlValorRecebido").Not.Nullable(); 
      Map(x => x.ValorTaxaCambio).Column("cmpVlTaxaCambio").Not.Nullable(); 
      Map(x => x.Observacao).Column("cmpDcObservacao"); 

      References(x => x.Repasse).Column("cmpIdRepasse"); 

      HasManyToMany(x => x.Downloads) 
       .Table("tblRecursoRepasseDownload") 
       .ParentKeyColumn("cmpIdRecursoRepasse") 
       .ChildKeyColumn("cmpIdDownload") 
       .AsBag().LazyLoad().Cascade.SaveUpdate(); 
     } 
    } 

    public class RepasseProdutoMap : ClassMap<RepasseProduto> 
    { 
     public RepasseProdutoMap() 
     { 
      Schema(ConfigInstances.ObterSchema("Sigma")); 
      Table("tblRepasseProduto"); 
      LazyLoad(); 

      Id(x => x.Id).GeneratedBy.Identity().Column("cmpIdRepasseProduto"); 

      Map(x => x.DataInicio).Column("cmpDtDatainicio").Not.Nullable(); 
      Map(x => x.DataTermino).Column("cmpDtDatatermino").Not.Nullable(); 
      Map(x => x.QtdProduto).Column("cmpInQuantidadeproduto").Not.Nullable(); 
      Map(x => x.QtdBeneficiado).Column("cmpIdQuantidadeBeneficiado").Not.Nullable(); 
      Map(x => x.PublicoBeneficiado).Column("cmpIdPublicoBeneficiado").CustomType(typeof(PublicoBeneficiado)); 

      References(x => x.Produto).Column("cmpIdProduto"); 
      References(x => x.Repasse).Column("cmpIdRepasse"); 

      HasMany(x => x.Atividades).AsBag().LazyLoad(); 
     } 
    } 

    public class RepasseProdutoAtividadeMap : ClassMap<RepasseProdutoAtividade> 
    { 
     public RepasseProdutoAtividadeMap() 
     { 
      Schema(ConfigInstances.ObterSchema("Sigma")); 
      Table("tblRepasseProdutoAtividade"); 
      LazyLoad(); 

      Id(x => x.Id).GeneratedBy.Identity().Column("cmpIdRepasseProdutoAtividade"); 

      Map(x => x.DataInicio).Column("cmpDtInicio").Not.Nullable(); 
      Map(x => x.DataTermino).Column("cmpDtTermino").Not.Nullable(); 
      Map(x => x.Descricao).Column("cmpDcAtividade").Not.Nullable(); 

      References(x => x.RepasseProduto).Column("cmpIdRepasseProduto"); 
     } 
    } 
} 

Когда я запрашиваю RepasseProduto то SQL генерируется с вопросом, запрос не Findout, как получить внешний ключ имя для отношений «один ко многим», как вы можете видеть ниже:

select repasse0_.cmpIdRepasse as cmpIdCol1_5_ 
repasse0_1_.cmpDtDataCriacao as cmpDtDat2_5_ 
repasse0_1_.cmpStSituacao as cmpStSit3_5_ 
repasse0_1_.cmpDcCancelamento as cmpDcCan4_5_ 
repasse0_1_.cmpIdRecurso as cmpIdRec5_5_ 
repasse0_.cmpDcDescricao as cmpDcDes2_7_ 
repasse0_.cmpVlValorRepasse as cmpVlVal3_7_ 
repasse0_.cmpDtDataInicio as cmpDtDat4_7_ 
repasse0_.cmpDtDataTermino as cmpDtDat5_7_ 
repasse0_.cmpIdUsuarioExecucao as cmpIdUsu6_7_ 
repasse0_.cmpIdUsuarioMonitoramento as cmpIdUsu7_7_ 
    from mre_sigma_dsv.dbo.tblRepasse repasse0_ 
     inner join mre_sigma_dsv.dbo.tblColaboracao repasse0_1_ 
      on repasse0_.cmpIdRepasse=repasse0_1_.cmpIdColaboracao 
     where (select cast(count(*) as INT) 
        from mre_sigma_dsv.dbo.tblRepasseProduto produtos1_ 
        where repasse0_.cmpIdRepasse=produtos1_.Repasse_id)>@p0 

Как вы можете видеть, последний внутренний select не определяет имя внешнего ключа от tblRepasseProduto до tblRepasse, а затем использует Repasse_id, который не представляет собой действительное поле таблицы.

Что мне делать? Я что-то упускаю при сопоставлении отношения моего подкласса?

ответ

2

Действительно не уверен, откуда находится столбец призрака, но есть другая проблема в приведенном выше сопоставлении. В отношениях one-to-manyvsmany-to-one, то есть в свободном HasManyпротивReferences, должен быть/находится ровно один столбец, представляющий это. Поэтому для этого нам нужно использовать один и тот же (один) столбец и таким образом изменить отображение.

RepasseMap : SubclassMap<Repasse>:

public RepasseMap() 
{ ... 
    // was: 
    // HasMany(x => x.RepassesRecebidos).AsBag().LazyLoad(); 
    // HasMany(x => x.Produtos).KeyColumn("cmpIdRepasseProduto").AsBag().LazyLoad(); 

    // should be 
    HasMany(x => x.RepassesRecebidos) 
     .KeyColumn("cmpIdRepasse").AsBag().LazyLoad(); 
    HasMany(x => x.Produtos) 
     .KeyColumn("cmpIdRepasse").AsBag().LazyLoad(); 
} 

RepasseRecebidoMap : ClassMap<RepasseRecebido>:

public RepasseRecebidoMap() 
{ ... 
    // the same column representing this relationship in table "tblRecursoRepasse" 
    References(x => x.Repasse).Column("cmpIdRepasse"); 

RepasseProdutoMap : ClassMap<RepasseProduto>:

public RepasseProdutoMap() 
{ ... 
    // the same column representing this relationship in table "tblRepasseProduto" 
    References(x => x.Repasse).Column("cmpIdRepasse"); 

Если это не поможет, то, пожалуйста, отправить запрос, который вы уже использовали и который породил эту странную связь.

Кроме того, в фрагменте Mapping выше вы вставляете классы сопоставления ... это неправильный/необходимый способ.

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