0

I'd like to know if the next problem can be solved in a different way in NHibernate.

Let's say we've this domain:

public class A 
{
     public virtual B LastAssociationWithB { get; set; }
     public virtual ICollection<B> CollectionAssociationOfB { get; set; }
}

public class B
{
     public virtual DateTime DateAdded { get; set; }
}

The LastAssociationWithB property represents one of the B persistent objects associated in the CollectionAssociationOfB collection property.

Actually, LastAssociationWithB represents the last B persistent object added by date.

So, in the domain, when a new B is added to CollectionAssociationOfB, it's also assigned to LastAssociationWithB.

This is a good way of later turning code into less complex LINQ queries.

Anyway, my question is: do you know any other approach to this? For example, some kind of many-to-one association that produces a SQL join under the hoods so you wouldn't need to have an explicit 1:n relation in the A table but it would maintain the class property?

Or is my current approach the recommended way of solving this scenario?

Side note: in the real-world scenario that CollectionAssociationOfB is an ordered list as ordering is specified in the NHibernate mapping configuration.

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
  • What exactly is your issue? It this working for you? Why do you not want a 1:n relation in the B table? For the CollectionOfB you have the DB relation right? And then you just store the last B added to that collection in another property. Is this property mapped at all? – MichaC Sep 22 '13 at 08:17
  • @Ela Sorry, it was a type: I was talking about *table of `A`*. – Matías Fidemraizer Sep 22 '13 at 08:43
  • I'm still not getting what you actually want to know ;) sorry. I mean, if you don't want to have A and B referencing each other, that should be fine, I mean, if you write a Linq query joining both tables, nhibernate will most likely generate a query with SQL join for you under the hoods. You could just store the ID of the last B in your A class and join A with B on that ID – MichaC Sep 22 '13 at 08:55
  • @Ela I was wondering if it was some missing feature in my knowledge about NHibernate so you can configure a many-to-one to a property specifying a query, thus you woulnd'n need to store that ID in the database and achieve the same result as if it would stored in the DB. – Matías Fidemraizer Sep 22 '13 at 08:58

1 Answers1

1

You could specify the relationship using a formula:

whether this is better or not is debatable.. it depends on your circumstances - one the one hand it ensures consistency, but on the other hand it will probably have a performance penalty when querying - so it really depends on your own specific case.

Another alternative is to use a trigger on insert into B to update the column in A. This has the downside of moving logic into the database, but it would ensure consistency without the potential performance penalty.

You could also achieve the equivalent of a trigger by using an NHibernate event to intercept saving B and then updating A - with the benefit of the logic remaining in your code, but the downside that any direct updates to the database could introduce inconsistency.

Of course both trigger options obfuscate the logic somewhat, as opposed to having a method on A or B that does the logic. I would personally probably put a method in A to add a new B and update the association, but then you would need to ensure that no-one updates the B collection directly and bypasses your method.

Martin Ernst
  • 5,629
  • 2
  • 17
  • 14
  • Your last suggested approach is the one I'm doing right now. Some domain class encapsulates the addition of a new B so it sets it to the property of A. *About the point of trigger*. Well, maybe it's not business at all. It could be understood as the *regular* behavior for this domain. And about the formula, I'll look forward for this. – Matías Fidemraizer Sep 23 '13 at 18:06
  • By the way, about the formula approach, this has a downside: in case of eagerly-loading `A`, the whole association of `B` won't be retrieved using an inner join or so, but with a separate query. Am I wrong? – Matías Fidemraizer Sep 23 '13 at 18:09
  • Yes with the formula approach, the ID of the latest B will be retrieved using a subquery - the performance hit will depend on your circumstances tho, it might not be noticeable – Martin Ernst Sep 24 '13 at 08:17
  • I see. Well, in my case I believe that it wouldn't be optimal because it's about a listing. Imagine N users requesting such listing. I believe that the "formal" solution is the best in my case (having the foreign key of B in A). – Matías Fidemraizer Sep 24 '13 at 10:37
  • There are lots of ways of solving or reducing any potential performance penalty - however until you profile it against real data, it's a bit pointless to pre-maturely optimize. The first decision should be clarity & maintainability of your code, and then only if necessary should you optimize your code. I'd imagine you could obviate any performance penalty by using caching, but I also wouldn't change anything because I doubt it would make much of a difference either way.. :) – Martin Ernst Sep 24 '13 at 16:15
  • You're right: premature optimization is the devil of software development. By the way, your info was useful ;) – Matías Fidemraizer Sep 24 '13 at 17:35