What is the best way to ensure there is only a single ORM model instance tied to a row in a database?

59 Views Asked by At

The Problem

We have an app that stores hierarchical data in a database. We have defined a POCO object which represents a row of data.

The problem is we need certain properties to be dependent on the item's children and others on their ancestors. As an example, if a ((great)grand)child has incomplete state, then implicitly all of its parents are also incomplete. Similarly, if a parent has a status of disabled, then all children should be implicitly disabled as well.

On the database side of things, everything works thanks to triggers. However, the issue we're having is then synching those changes to any in-memory ORM objects that may have been affected.

That's why we're thinking to do all of this, we need to ensure there is only ever one model instance in memory for any specific row in the database. That's the crux of the entire problem.

We're currently doing that with triggers in the DB, and one giant hash-set of weak references to the objects keyed on the database's ID for the in-memory ORM objects, but we're not sure that's the proper way to go.

Initial Design

Our 'rookie' design started by loading all objects from the database which quickly blew out the memory, let alone took a lot of time loading data that may never actually be displayed in the UI as the user may never navigate to it.

Attempt 2

Our next attempt expanded on the former by dynamically loading only the levels needed for actual display in the UI, which greatly sped up loading, but now doesn't allow the state of the hierarchy to be polled without several calls to the database.

Attempt 2B

Similar to above, but we added persistent 'implicit status' fields which were updated via triggers in the database. That way if a parent was disabled, a trigger updated all children accordingly. Then the model objects simply refreshed themselves with the latest values from the database. This has the down-side of putting some business logic in the model layer and some in the database triggers as well as making both database writes and reads needed for every operation.

Fully Dynamic

This time we tried to make our models 'dumb' and removed our business layer completely from the code, moving that logic entirely to the database. That way there was only single-ownership of the business rules. Plus, this guaranteed bad data couldn't be inserted into the database in the first place. However, here too we needed to constantly poll the database for the 'current' values, meaning some logic did have to be built in to know which objects needed to be refreshed.

Fully Dynamic with Metadata

Similar to above, but all write calls to the database returned an update token that told the models if they had to refresh any loaded parents or children.

I'm hoping to get some feedback from the SO community on how to solve this issue.

0

There are 0 best solutions below