Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6194231
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T03:15:40+00:00 2026-05-24T03:15:40+00:00

The project I am working on requires data in our system to be synchronized

  • 0

The project I am working on requires data in our system to be synchronized with that of another (the other system is quite popular which is why synchronization is so important). However, I am having a weird issue when I attempt to update an existing entity that has a composite id.

The problem is that whenever the entity to be updated is retrieved (using Get) prior to calling Merge, it does not work (the changes are not persisted to the DB but no exception is thrown). When I remove the call to Get, updating the entity works. Knowledge on whether the entity exists is needed because if it is being created, part of the composite id needs to be generated.

bool exists = ScanForInstance(instance);
using (var session = SessionFactoryFactory.GetSessionFactory<T>().OpenSession())
{
    if (exists)
    {
        instance = (T)session.Merge(instance);
    }
    else
    {
        KeyGenerator.Assign<T>(instance);
        newId = session.Save(instance);
    }

    session.Flush();
}

The Get call is made in the ScanForInstance method:

private bool ScanForInstance<T>(T instance)
    where T : class
{
    var id = IdResolver.ResolveObject<T>(instance);
    using (var session = SessionFactoryFactory.GetSessionFactory<T>().OpenStatelessSession())
    {
        return session.Get<T>(id) != null;
    }
}

The IdResolver is used for determining what should be used for the id (the value of a single key in a mapping, otherwise the object itself for entities with composite ids).

Like I said, if I remove the call to Get it works fine. It works fine for all other operations as well (create, read, and deletes). All operations, including updating, works fine for entities with single keys.


The DB is Pervasive and there are a certain number of restrictions:

  • No, I cannot change any of the schema (I see that as a frequent response to problems with FNB).
  • I do not want to just delete then insert as there are some columns we do not sync back to our system and I do not want to wipe these out

UPDATED: I’ve added a simple example that people can copy/paste to test this weird behavior (if it is in fact universal). I’m hoping people will do this to at least confirm my problem.

Type to be mapped, Fluent mapping:

public class ParentType
{
    public virtual long AssignedId { get; set; }

    public virtual long? GeneratedId { get; set; }

    public virtual string SomeField { get; set; }

    public override bool Equals(object obj)
    {
        return Equals(obj as ParentType);
    }

    private bool Equals(ParentType other)
    {
        if (ReferenceEquals(this, other)) return true;
        if (ReferenceEquals(null, other)) return false;

        return AssignedId == other.AssignedId &&
            GeneratedId == other.GeneratedId;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = GetType().GetHashCode();
            hash = (hash * 31) ^ AssignedId.GetHashCode();
            hash = (hash * 31) ^ GeneratedId.GetHashCode();

            return hash;
        }
    }
}

public class ParentMap : ClassMap<ParentType>
{
    public ParentMap()
    {
        Table("STANDARDTASKITEM");

        CompositeId()
            .KeyProperty(x => x.AssignedId, "STANDARDTASK")
            .KeyProperty(x => x.GeneratedId, "STANDARDTASKITEM");

        Map(x => x.SomeField, "DESCRIPTION");

        Not.LazyLoad();
    }
}

Don’t mind the fact it is called ‘ParentType.’ I don’t actually have any other mappings with this and don’t actually use the type as a parent type in this example. It is called this because I’m about to open another question that does involve problems with composite ids and inheritance (DON’T USE COMPOSITE ID’S! 😀).

For the actual testing, I just created a console project in VS with this as the Program.cs:

static void Main(string[] args)
{
    var smFactory = Fluently.Configure()
        .Database(() => new OdbcPersistenceConfigurer()
            .Driver<OdbcDriver>()
            .Dialect<GenericDialect>()
            .Provider<DriverConnectionProvider>()
            .ConnectionString(BuildSMConnectionString())
            .ProxyFactoryFactory(typeof(NHibernate.ByteCode.Castle.ProxyFactoryFactory))
            .UseReflectionOptimizer()
            .UseOuterJoin())
            .Mappings
            (m => 
                m.FluentMappings.Add<ParentMap>()
            );

    var sessionFactory = smFactory.BuildSessionFactory();

    var updatedInstance = new ParentType
    {
        AssignedId = 1,
        GeneratedId = 13,
        SomeField = "UPDATED"
    };

    bool exists;

    using (var session = sessionFactory.OpenStatelessSession())
    {
        exists = session.Get<ParentType>(updatedInstance) != null;
    }

    using (var session = sessionFactory.OpenSession())
    {
        if (exists)
        {
            session.Merge(updatedInstance);

            session.Flush();
        }
    }
}

private static string BuildSMConnectionString()
{
    // Return your connection string here
}

class OdbcPersistenceConfigurer : PersistenceConfiguration<OdbcPersistenceConfigurer, OdbcConnectionStringBuilder>
{

}

I know that adding this sample is only slightly more helpful since anyone wanting to test this would either need to change the ParentType field to conform to a table that they already have in their own DB, or add a table to match what is mapped in ParentType. I’m hoping someone will do this at least out of curiosity now that I’ve given a good head-start on testing.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T03:15:41+00:00Added an answer on May 24, 2026 at 3:15 am

    Well, I’ve at least figured out a solution to my problem, but not why. My solution was to create a new type that encompassed the properties I was using as the composite id:

    public class CompositeIdType
    {
        public virtual long AssignedId { get; set; }
    
        public virtual long GeneratedId { get; set; }
    
        public override bool Equals(object obj)
        {
            return Equals(obj as CompositeIdType);
        }
    
        private bool Equals(CompositeIdType other)
        {
            if (ReferenceEquals(this, other)) return true;
            if (ReferenceEquals(null, other)) return false;
    
            return AssignedId == other.AssignedId &&
                GeneratedId == other.GeneratedId;
        }
    
        public override int GetHashCode()
        {
            unchecked
            {
                int hash = GetType().GetHashCode();
    
                hash = (hash * 31) ^ AssignedId.GetHashCode();
                hash = (hash * 31) ^ GeneratedId.GetHashCode();
    
                return hash;
            }
        }
    }
    

    Then, substitute the properties in ParentType for a reference to this new type:

    public class ParentType
    {
        public virtual CompositeIdType Key { get; set; }
    
        public virtual string SomeField { get; set; }
    }
    

    With those changes, the new mapping would be:

    public class ParentMap : ClassMap<ParentType>
    {
        public ParentMap()
        {
            Table("STANDARDTASKITEM");
    
            CompositeId<CompositeIdType>(x => x.Key)
                .KeyProperty(x => x.AssignedId, "STANDARDTASK")
                .KeyProperty(x => x.GeneratedId, "STANDARDTASKITEM");
    
            Map(x => x.SomeField, "DESCRIPTION");
    
            Not.LazyLoad();
        }
    }
    

    After all these changes are made, Merge works even when Get is called prior to the Merge call. My best bet is the non-generic form of CompositeId is not doing something correctly or that the mapping it is making is not working well with NH when you call Merge on an entity that uses it (I’d like to go into the source of FNH to fix it if that is the case but I’ve already spent too much time figuring out how to bypass this problem).

    This is all well and good but this would require me to create a new type for each entity I am mapping, or at least a new type for an id with a different number of keys (ie a type with 2 keys, a type with 3 keys, etc.).

    To avoid this, I can hack it so that you add a reference of the same type you are mapping and set the reference to this in the constructor:

    public class ParentType
    {
        public ParentType()
        {
            Key = this;
        }
    
        public virtual ParentType Key { get; set; }
    
        public virtual long AssignedId { get; set; }
    
        public virtual long GeneratedId { get; set; }
    
        public virtual string SomeField { get; set; }
    
        public override bool Equals(object obj)
        {
            return Equals(obj as ParentType);
        }
    
        private bool Equals(ParentType other)
        {
            if (ReferenceEquals(this, other)) return true;
            if (ReferenceEquals(null, other)) return false;
    
            return AssignedId == other.AssignedId &&
                GeneratedId == other.GeneratedId;
        }
    
        public override int GetHashCode()
        {
            unchecked
            {
                int hash = GetType().GetHashCode();
    
                hash = (hash * 31) ^ AssignedId.GetHashCode();
                hash = (hash * 31) ^ GeneratedId.GetHashCode();
    
                return hash;
            }
        }
    }
    

    Then the mapping would be:

    public class ParentMap : ClassMap<ParentType>
    {
        public ParentMap()
        {
            Table("STANDARDTASKITEM");
    
            CompositeId<ParentType>(x => x.Key)
                .KeyProperty(x => x.AssignedId, "STANDARDTASK")
                .KeyProperty(x => x.GeneratedId, "STANDARDTASKITEM");
    
            Map(x => x.SomeField, "DESCRIPTION");
    
            Not.LazyLoad();
        }
    }
    

    I have tested this for updating and inserting using Merge with Get getting called prior to the merge and surprisingly IT WORKS. I’m still on the fence on which fix to use (the new type encompassing the composite id or the self-reference) as the self-reference seems a little to hacky for my tastes.

    If anyone finds out WHY this didn’t work originally I’d still like to know…

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a project I'm working on that requires our WPF application read SMS
I'm working on a project which requires us developing our own intermediate SMTP relay
I am working on a project that requires reading text files, extracting data from
I'm working on a small project that requires some of our users to be
I am working on a project that requires that I render XML data (that
I'm working on a university project that requires encrypted data to be sent from
I'm working on a project that requires me to load some of the data
A project I'm working on requires serializing a data structure before shutting down and
I am working on a project that requires the manipulation of enormous matrices, specifically
I am working on a project that requires a number of icons generated from

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.