Nhibernate SubClass关系生成错误的SQL

时间:2013-12-26 13:31:09

标签: nhibernate fluent-nhibernate fluent-nhibernate-mapping

我正在使用每种类型的表(TPT)在Nhibernate v3.3.1.4000 中进行继承。我发现任何一对多的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时,查询没有找到如何获取一对多关系的外键名称,如下所示:

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找不到从tblRepasseProdutotblRepasse的外键名称,然后使用不{0}的Repasse_id表示有效的表字段。

我该怎么办?我在映射我的子类关系时是否遗漏了什么?

1 个答案:

答案 0 :(得分:2)

真的不确定ghost列的来源,但上面的映射还有其他问题。在关系one-to-many vs many-to-one中,即流利的HasMany vs 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代码段中,您正在嵌套映射类...这不是正确/必需的方式。