Fluent Nhibernate - Composite Key Mapping

Asked

Viewed 1,102 times

2

Greetings,

I’m having a hard time and I can’t fix it.

I have an application where I created the mapping and everything was working perfectly, but now I need to change it and that’s where the problem arises:

I used Fluent Nhibernate for the ORM.

I need to create the mapping using a composite key, IE, in SQL language would look something like this:

select
    *
from
    t1
inner join
    t2
        on  t1.codigo = t2.codigo
        and t1.versao = t2.versao;

And I can’t map Join’s "and".

My mapping is like this:

public class T1Map : ClassMap<T1>{
    public T2Map() {
        Table("TB_WF_T1");
        Id(x => x.Codigo, "CD_T1").GeneratedBy.Sequence("SEQ_TB_WF_T1");
        Map(x => x.Versao, "CD_VERSAO");
        HasMany(x => x.T2).KeyColumn("FK_CODIGO_T1").LazyLoad().Inverse().Cascade.SaveUpdate();
    }        
}

public class T2Map : ClassMap<T2>{
    public T2Map() {
        Table("TB_WF_T2");
        Id(x => x.Codigo, "CD_T2").GeneratedBy.Sequence("SEQ_TB_WF_T2");
        Map(x => x.Versao, "CD_VERSAO");
        References(x => x.T1).Column("FK_CODIGO_T1").LazyLoad().Cascade.None();
    }
}

My question is how I map both the "CODE" field and the "VERSION" field".

Is there any way to perform this mapping?

Any hint anyone can help me with, I’d be most grateful.

  • Were you able to solve the problem with my answer below? If yes select my answer as solved. Otherwise I can still help you with something.

  • I’ll try now... I’ve already put the result.

  • Danilo, I’m going to need to make some modifications to the structure of my application to perform the tests. As soon as I’m done, I’ll let you know.

1 answer

3

I use the Compositeid() of Fluentnhibernate, and use the Ference. Hasmany is if it’s a collection I want to upload together. By your code you should already know the difference.

CompositeId()
            .KeyReference(x => x.Id, "idB")//se for uma referencia(entidade)
            .KeyProperty(x => x.Id2, "idB2");//se for uma propriedade(int/long)

Follow an example if it is a class with Keyproperty and Keyreference: (Esse Link)

    public class TestChildMap : ClassMap<TestChild>
    {
        public TestChildMap()
        {
            Table("TestChild");
            CompositeId()
                .KeyProperty(x => x.ChildName, "ChildName")
                .KeyReference(x => x.Parent, "TestParentId");
    Map(x => x.Age);
            References(x => x.Parent, "TestParentId")
     .Not.Insert();  //  will avoid "Index was out of range" error on insert
    }

Here’s an example if it’s a class with Keyreference:

public class MapEmpresaProduto : MapBase<EmpresaProduto>
    {
        public MapEmpresaProduto()
        {
            Table("EmpresaProduto");
            CompositeId()
                .KeyReference(x => x.Empresa, "IdEmpresa")
                .KeyReference(x => x.Produto, "IdProduto");

            References(x => x.Empresa)
                .Not.Nullable()
                .Fetch.Join()
                .Cascade.SaveUpdate()
                .Column("IdEmpresa")//linko o KeyReference(x => x.Empresa, "IdEmpresa") atraves do column name.
                .ReadOnly();

            References(x => x.Produto)
                .Not.Nullable(

)
                .Fetch.Join()
                .Cascade.SaveUpdate()
                .Column("IdProduto")
                .ReadOnly();
        }
    }

My entity Loan:

public class EmpresaProduto : EntidadeAuditavelSemId
    {
        public virtual Produto Produto { get; set; }

        public virtual Empresa Empresa { get; set; }

        protected EmpresaProduto()
        {
        }
        public EmpresaProduto(Empresa empresa, Produto produto) : this()
        {
            Produto = produto;
            Empresa = empresa;
        }

        public override bool Equals(object entity)
        {
            if (entity == null || !(entity is EmpresaProduto))
            {
                return false;
            }

            // Mesmas instâncias devem ser consideradas iguais
            if (ReferenceEquals(this, entity))
            {
                return true;
            }

            // Objetos transientes não são considerados iguais
            var other = (EmpresaProduto)entity;
            var typeOfThis = GetType();
            var typeOfOther = other.GetType();
            if (!typeOfThis.IsAssignableFrom(typeOfOther) && !typeOfOther.IsAssignableFrom(typeOfThis))
            {
                return false;
            }

            return Produto.Id.Equals(other.Produto.Id) && Empresa.Id.Equals(other.Empresa.Id);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                var hash = GetType().GetHashCode();
                hash = (hash * 31) ^ Produto.GetHashCode();
                hash = (hash * 31) ^ Empresa.GetHashCode();

                return hash;
            }
        }
    }

OBS: I have done many tests and Sqlserver so far stood out, being index created with strange and wrong names in MYSQL and postgress. So if your seat is not sqlserver be careful. (The problem is really in the connector and not in the Fluent itself).

  • Danilo, it didn’t work. In this excerpt you gave me as an example, where I specify what is the second clause (composite key) for Join?

  • 1

    is I really didn’t understand what Cvoce wants... in the code posted you are using in 'public class Exclusaomap' both Compositeid() and Id(), this is confusing me, what is the key of the table Exclusions? If it is a composite key, Compositeid(), if not Id() should be used. This mapping I am also realizing that it is not necessary, You can make 2 queries in LINQ with a Where(x => x.Code == code && x.version == version)... So it’s really confusing. From a researched in some examples in English, it might improve your idea of how to do this.

  • I think I messed up when I posted the classes. Tomorrow I post as I was and what I need, it will be easier for you to help me.

  • Danilo, I described below what I need and how it is. See if you understand and if you can help me.

  • To solve your problem, the Versao field Must be a Foregnkey/Primarykey Because it is not usual to make a Join for basic properties... I will not be able to solve your problem, maybe someone can help me to solve this mystery kkk

  • 1

    http://stackoverflow.com/questions/8855135/fluent-nhibernate-mapping-one-to-many-using-2-columns this link might help you.

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.