Hello all,
We heavily use inheritance in our data layer, almost every class we have
is inherited from a base class and there are several derivees.
Recently we tried to move a pretty big dynamic HQL query that was
getting out of hand and was resulting in a lot of code duplication.
The problem we're facing is that one of the classes uses a *<component>
*mapping for a property, while another derivee uses a *many-to-one* for
the same property.
Because of QueryOver needing explicit joins to be defined, I can't seem
to easily create just one query that applies to both classes. Trying to
define a JoinAlias() for the <component> relationship results in an
error, and queries for the derivee with many-to-one don't work without a
JoinAlias(). It seems awkward to need to adapt my data access code based
on the way the property is defined in the mapping, and seems like a
leaky abstraction API design issue.
I was able to work around this with some very ugly helper methods that
return various *System.Linq.Expressions.Expression<Func<* return types
based on which class is being worked on.
Here's some code:
Derivee1Repository.cs:
protected virtual
System.Linq.Expressions.Expression<Func<TDerivee,object>>
CategoryNameExpression()
{
return p => CategoryAlias.CategoryName; // for the many-to-one
}
Derivee2Repository.cs:
protected virtual
System.Linq.Expressions.Expression<Func<TDerivee,object>>
CategoryNameExpression()
{
return p => p.Category.CategoryName; // for the component, can't
use CategoryAlias here, it will throw an exception that Derivee does not contain a
property called CategoryName
}
Then the joint DeriveeRepositoryBase.cs could do, for example:
query.Select(CategoryNameExpression())
Also, another problem seems to be that casts on aliases do not seem to
work at all:
Derivee1Repository.cs:
query.JoinAlias(p => p.BillingInfo, () => BillingInfoAlias); //
separate table
query.JoinAlias(() => BillingInfoAlias.PaymentMethod, () =>
PaymentMethodAlias);
Derivee2Repository.cs:
query.JoinAlias(() => p.BillingInfo.PaymentMethod, () =>
PaymentMethodAlias); // here billinginfo is just a component of the same table:
DeriveeRepositoryBase.cs:
query.Select(()=>((CreditCard)PaymentMethodAlias).ExpirationDate); //
exception, Derivee does not contain property called ExpirationDate
query.Select(()=>PaymentMethodAlias.Id); // Id is defined on
base, this works
I wasn't able to use Projections.Property() either as a parameter for
the method, unless someone can help with an idea on how to do the cast.
It would be nice if there was a way for JoinAlias() to work with (or
silently ignore) components as well, allowing an alias to be defined and
used the same as if it was a separate table. *OR*, even better would be
if there was a way for QueryOver to allow Linq-like auto-joins of tables
if they're needed. That would simplify our code tremendously.
Ideally, I'd use Nhibernate linq for this, which does not have any of
these problems as far as I can tell but I need to call a custom function
that is specified in our custom Dialect, and I wasn't able to find how
to call a custom function with nhibernate linq (if it's at all possible).
So, to recap, the questions are:
1) Is the QueryOver behavior going to be fixed? Are there any plans on
making it more like linq and not requiring explicit joins for
everything? It's tedious and requires intimate knowledge of how mappings
are defined, which breaks abstraction layers.
2) Any clues on the cast issue?
3) Is it possible to use nhibernate linq to call a custom function
defined in the dialect? (it's a custom AddDays(prop1, prop2) function
that we need, were both prop1 and prop2 are columns in the table)
Thanks,
Andrei
--
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en.