because that class is registered as entity? -- Fabio Maulo
El 05/05/2011, a las 10:59, lege <[email protected]> escribió: > Ok, it appears I was wrong and nhibernate linq also suffers from the > same problem with components, which I think is definitely a bug. > > I was able to integrate my custom sql dialect function calls into > nhibernate linq using some generator classes derived from > BaseHqlGeneratorForMethod. > (https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/ > nhibernate/src/NHibernate.Test/Linq/CustomExtensionsExample.cs) > > Everything works fine for the class that has the property mapped via > many-to-one but the one the one with component it fails when executing > the query with the following error: > > Invalid join: p.BillingInfo > [.Select(.Where(.Where(.Where(NHibernate.Linq.NhQueryable`1[.... > > at > NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.CreateFromJoinElement(IASTNode > path, IASTNode alias, Int32 joinType, IASTNode fetchNode, IASTNode > propertyFetch, IASTNode with) in d:\CSharp\NH\nhibernate\src\NHibernate > \Hql\Ast\ANTLR\HqlSqlWalker.cs: line 694 > at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.joinElement() in d:\CSharp\NH > \nhibernate\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: > line 3955 > at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.fromElement() in d:\CSharp\NH > \nhibernate\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: > line 3617 > at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.fromElementList() in d:\CSharp > \NH\nhibernate\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: > line 3391 > at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.fromClause() in d:\CSharp\NH > \nhibernate\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: > line 3308 > at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.unionedQuery() in d:\CSharp\NH > \nhibernate\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: > line 1645 > at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.query() in d:\CSharp\NH > \nhibernate\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: > line 1510 > at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectStatement() in d:\CSharp > \NH\nhibernate\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: > line 536 > at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.statement() in d:\CSharp\NH > \nhibernate\src\NHibernate\Hql\Ast\ANTLR\Generated\HqlSqlWalker.cs: > line 435 > at NHibernate.Hql.Ast.ANTLR.HqlSqlTranslator.Translate() in d:\CSharp > \NH\nhibernate\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs: > line 589 > at > NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.DoCompile(IDictionary`2 > replacements, Boolean shallow, String collectionRole) in d:\CSharp\NH > \nhibernate\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs: line > 396 > at > NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IASTNode > ast, String queryIdentifier, String collectionRole, Boolean shallow, > IDictionary`2 filters, ISessionFactoryImplementor factory) in d:\CSharp > \NH\nhibernate\src\NHibernate\Hql\Ast\ANTLR > \ASTQueryTranslatorFactory.cs: line 44 > at > NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String > queryIdentifier, IQueryExpression queryExpression, String > collectionRole, Boolean shallow, IDictionary`2 filters, > ISessionFactoryImplementor factory) in d:\CSharp\NH\nhibernate\src > \NHibernate\Hql\Ast\ANTLR\ASTQueryTranslatorFactory.cs: line 27 > at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String > expressionStr, IQueryExpression queryExpression, String > collectionRole, Boolean shallow, IDictionary`2 enabledFilters, > ISessionFactoryImplementor factory) in d:\CSharp\NH\nhibernate\src > \NHibernate\Engine\Query\HQLExpressionQueryPlan.cs: line 23 > at > NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression > queryExpression, Boolean shallow, IDictionary`2 enabledFilters) in d: > \CSharp\NH\nhibernate\src\NHibernate\Engine\Query\QueryPlanCache.cs: > line 89 > at > NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression > queryExpression, Boolean shallow) in d:\CSharp\NH\nhibernate\src > \NHibernate\Impl\AbstractSessionImpl.cs: line 302 > at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression > queryExpression) in d:\CSharp\NH\nhibernate\src\NHibernate\Impl > \AbstractSessionImpl.cs: line 258 > at NHibernate.Linq.NhQueryProvider.PrepareQuery(Expression expression, > ref IQuery query, ref NhLinqExpression nhQuery) in d:\CSharp\NH > \nhibernate\src\NHibernate\Linq\NhQueryProvider.cs: line 42 > at NHibernate.Linq.NhQueryProvider.Execute(Expression expression) in d: > \CSharp\NH\nhibernate\src\NHibernate\Linq\NhQueryProvider.cs: line 101 > at Remotion.Data.Linq.QueryableBase`1.GetEnumerator() > > > Where p.BillingInfo is the component here. It's unclear to me why it > tries to join on the component, any ideas? > > > > On May 5, 2:07 am, lege <[email protected]> wrote: >> The id of the entity is not being used explicitly anywhere. The >> cascading mode takes care of any updates to this property, and >> otherwise everything works fine. >> >> Nhibernate linq and hql can adapt the sql being executed easily on the >> fly, it's just QueryOver and Criteria that are not. >> >> On May 5, 1:55 am, Fabio Maulo <[email protected]> wrote: >> >> >> >> >> >> >> >>> "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." >> >>> The DB can be old but I would know why/when you need an Entity with its ID >>> as a component. >>> I have used a similar trick but with a read-only view and was a very ugly >>> quick solution done 4 years ago. >>> Believe me that is not a good idea especially if you are doing it with a >>> read-write entity and/or with the cache enabled... compared the QueryOver >>> "problem" is nothing. >> >>> On Wed, May 4, 2011 at 7:42 PM, lege <[email protected]> wrote: >>>> Yes Fabio, same property of the same type. It's a legacy database >>>> schema and it's pretty much impossible to change right now. >> >>>> On May 4, 11:12 pm, Fabio Maulo <[email protected]> wrote: >>>>> "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." >> >>>>> Same property of the same Type ? >> >>>>> On Wed, May 4, 2011 at 4:57 PM, Andrei Alecu <[email protected] >>>>> wrote: >> >>>>>> 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. >> >>>>> -- >>>>> Fabio Maulo >> >>>> -- >>>> 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. >> >>> -- >>> Fabio Maulo > > -- > 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. > -- 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.
