2
votes

I have an entity with a CompositeId that won't insert new rows to the database using SaveOrUpdateCopy. The INSERT statement generated by NHibernate is populated with "?" for the value of every field. It inserts fine with SaveOrUpdate, it updates fine with either SaveOrUpdateCopy or SaveOrUpdate, and any entity without a CompositeId inserts/updates fine with SaveOrUpdateCopy. I don't want to create an if/then looking for entities with CompositeId to decide if it should use SaveOrUpdate or SaveOrUpdateCopy. Is there some trick to getting SaveOrUpdateCopy to work with entities with CompositeId?

Here's the code (names changed to protect the innocent):

public class MyEntity
    {
        public virtual Int32 FirstProperty { get; set; }
        public virtual string SecondProperty { get; set; }
        public virtual string DataText { get; set; }

        public override int GetHashCode( )
        {
            int hashCode = 0;
            hashCode = hashCode ^ FirstProperty.GetHashCode() ^
                       SecondProperty.GetHashCode();
            return hashCode;
        }

        public override bool Equals( object obj )
        {
            MyEntity toCompare = obj as MyEntity;
            if( toCompare == null )
            {
                return false;
            }
            return ( GetHashCode() != toCompare.GetHashCode() );
        }
    }
public MyEntityMap()
        {
            CompositeId()
                .KeyProperty(x => x.FirstProperty, "first_property")
                .KeyProperty(x => x.SecondProperty, "second_property");

            Map(x => x.DataText, "data_text")
                .Nullable();

            Table("dbo.my_entity");
        }

Database call:

public MyEntity GetMyEntity(long firstProperty, string secondProperty)
        {
            using (var session = sessionFactory.OpenSession())
            {
                var result = from entity in
                                session.Linq()
                            where entity.FirstProperty == firstProperty
                                  && entity.SecondProperty== secondProperty
                            select entity;
                return result.Count() > 0 ? result.First() : null;
            }
        }

Database save:

using (var session = sessionFactory.OpenSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    try
                    {
                        session.SaveOrUpdateCopy(entity);
                        transaction.Commit();
                    }
                    catch(Exception ex)
                    {
                        transaction.Rollback();
                        throw;
                    }
                }
            }
2

2 Answers

1
votes

Add a version property to the composite key class, see this article for an in-depth explanation.

0
votes

Hi I use compositeId with FluentnHibernate but my implementation of the Equals and GetHashCode is different. This one class that have 7 fields as Key:

public class PresupuestoGastoPromocion

{
    public PresupuestoGastoPromocion() { }

    public virtual int Año { get; set; }
    public virtual int Mes { get; set; }
    public virtual int PartidaId { get; set; }
    public virtual string Equipo { get; set; }
    public virtual string CodFamilia { get; set; }
    public virtual string GDP { get; set; }
    public virtual int TipoPresupuestoId { get; set; }
    public virtual float Monto { get; set; }
    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;
        var t = obj as PresupuestoGastoPromocion;
        if (t == null)
            return false;
        if (CodFamilia == t.CodFamilia && Año == t.Año && Mes == t.Mes && TipoPresupuestoId == t.TipoPresupuestoId && Equipo == t.Equipo && PartidaId == t.PartidaId && GDP == t.GDP)
            return true;
        return false;
    }
    public override int GetHashCode()
    {
        return (CodFamilia + "|" + Año + "|" + Mes + "|" + TipoPresupuestoId + "|" + Equipo + "|" + PartidaId + "|" + GDP).GetHashCode();
    }

}



public class PresupuestoGastoPromocionMap : ClassMap<PresupuestoGastoPromocion>
{
    public PresupuestoGastoPromocionMap()
    {
        Table("PresupuestoGastoPromocion");
        CompositeId()
            .KeyProperty(x => x.Año)
            .KeyProperty(x => x.Mes)
            .KeyProperty(x => x.TipoPresupuestoId)
            .KeyProperty(x => x.CodFamilia, "Cod_Familia")
            .KeyProperty(x => x.Equipo)
            .KeyProperty(x => x.GDP)
            .KeyProperty(x => x.PartidaId);

        Map(x => x.Monto).Column("Monto");


    }
}

I hope this will help you.