The docs as do the comments claim Equals compares the _persistent state_
which I take to mean the PRIMITIVE (P) type.
Take for instance, we have a DECIMAL database mapping, to a CLR UINT64 in
the apporpriate scale and precision.
Equals is not seeing DECIMAL, which I would expect, but rather, UINT64.
Which is part and partial my confusion over this issue.
In the following base implementation, assuming NH docs, comments, etc, are
accurate, then this should never throw. But it is throwing, because object
value is UINT64.
public virtual new bool Equals(object x, object y)
{
static object Normalize(object value) => value switch
{
DBNull or null => DBNull.Value,
P p => p,
_ => throw new InvalidOperationException($"Unexpected value type:
'{value.GetType().FullName}'.")
};
var (xp, yp) = (Normalize(x), Normalize(y));
return (xp is null && yp is null)
|| (xp is DBNull && yp is DBNull)
|| ReferenceEquals(x, y)
|| Equals(xp, yp);
}
So my guess is, we want to be comparing values of type P, but can also see
values of type R (returned types), so need to disassemble them accordingly,
presumably from cached.
Anyone with any insight into this, please chime in? Thanks...
On Friday, July 25, 2025 at 11:25:43 PM UTC-4 Michael W Powell wrote:
> Perhaps making it harder than it needs to be. The interfaces both
> indicating literally equality and hash codes _of the persistent state_ that
> is of the P primitive types, I gather. If so no biggie, that's a simple
> correction to make.
>
> On Friday, July 25, 2025 at 10:58:19 PM UTC-4 Michael W Powell wrote:
>
>> Hello,
>>
>> I am at a point now implementing some user types, things are loading from
>> the database correctly, I can work with the models, make adjustments via
>> services and WPF UI views, view models, all that is working beautifully.
>>
>> Now I am doing the last leg of the game plan: persisting back to the
>> database, which as I can gather from the traces, StackOverflowExceptions,
>> etc, revolves around negotiating Equals: A LOT, and a lot of navigation to
>> and/or from assembed and/or dissassembled form factors. Which depending
>> upon the user type implementation, can be tricky.
>>
>> Which is part partial my question. What is the general expection, i.e.
>> persistence 'protocol' from an NHibernate perspective, navigating the
>> persistence conversation.
>>
>> Our approach is also generally to implement a P or R based generic user
>> type at base (i.e. primitive versus returned types), especially when we
>> want to do things such as negotiate NodaTime constructs, sometimes also
>> JSON based Newtonsoft.Json.Linq constructs; whch as I mentioned, works
>> beautifully querying and loading from the database.
>>
>> From what I can also determine, user types sometimes also cached,
>> although from the lack of documentation, we are not hundred percent clear
>> in which form, either P or R.
>>
>> I've implemented the assembly and disassembly generally to use switch
>> expressions with strategically placed pattern matching in order to isolate
>> P from R in a broad range of use cases. But still finding a StackOverflow
>> slip through the cracks here and there.
>>
>> Overall, we are familiar with ORM in general, usually involving
>> comparison between two datasets, so I'd guess minimally at a primitive
>> level, but what is cached, the assembled version, and to make the
>> apporpriate comparison that does not blow up the stack.
>>
>> So I am here to ask the question: what sort of protocol, assy, disassy,
>> caching, can we expect, negotiating the persistence sequence?
>>
>> Thanks!
>>
>> Best,
>>
>> Michael W. Powell
>>
>>
--
You received this message because you are subscribed to the Google Groups
"Fluent NHibernate" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/fluent-nhibernate/7332297c-c1e1-4449-bf5e-5f8e104de206n%40googlegroups.com.