Home
Help
Register
Log in

Search

 
   Active Threads  

You are here: Home > LLBLGen Pro > LLBLGen Pro Runtime Framework> NullReferenceException when using PrefetchPath
 

Pages: 1
LLBLGen Pro Runtime Framework
NullReferenceException when using PrefetchPath
Page:1/1 

  Print all messages in this thread  
Poster Message
wtijsma
User



Location:
Amsterdam
Joined on:
18-Apr-2006 15:46:26
Posted:
252 posts
# Posted on: 10-Feb-2011 13:14:31.  
Hi,

One of my customers have an issue with a construct that used to work in older assembly versions, but in the most recent builds of the (2.6 and 3.0) assemblies it fails.

Because the type of construct is used in many places but doesn't work anymore it prevents them from a quick update path to the latest version (2.6 or 3.0).

Now the code is actually wrong, but they have similar constructs in many places that all fail with the same message. This code runs on the NorthWind database:


Code:

[TestMethod]
     public void SelectRelatedEntityIssue()
     {
         IQueryable<CurrencyRateEntity> q = metaData.CurrencyRate;
         q = q.WithPath(a => a.Prefetch(c => c.Currency));
         q = q.Where(d => d.CurrencyRateId == 1);
        
         IQueryable<CurrencyEntity> currency = from s in q select s.Currency;
         Console.WriteLine(currency.FirstOrDefault().CurrencyCode);
                
        }


The Prefetch Path here isn't necessary (removing it fixes the problem), and the way of selecting a currency through another entity is also a bit strange, but maybe the error message can be a bit clearer if it can't be fixed.

This is the exception:

Code:
Test method AdventureWorks.Web.Tests._99_BugsReproduction.SelectRelatedEntity.SelectRelatedEntityIssue threw exception:
System.NullReferenceException: Object reference not set to an instance of an object.
at SD.LLBLGen.Pro.ORMSupportClasses.PersistenceCore.DetermineDifferentValuesForParameterizedPPath(IEntityCollectionCore rootEntities, IPrefetchPathCore prefetchPath, IPrefetchPathElementCore currentElement, Hashtable values) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.0\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Persistence\PersistenceCore.cs: line 695
at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchPrefetchPath(IEntityCollection2 rootEntities, IRelationPredicateBucket filterBucket, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IPrefetchPath2 prefetchPath, Boolean forceParameterizedPPath) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.0\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs: line 5171
at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket filterBucket, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList excludedIncludedFields, Int32 pageNumber, Int32 pageSize) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.0\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\AdapterSpecific\DataAccessAdapterBase.cs: line 2469
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProvider2.ExecuteEntityProjection(QueryExpression toExecute) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.0\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProvider2.cs: line 140
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.ExecuteExpression(Expression handledExpression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.0\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProviderBase.cs: line 261
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.Execute(Expression expression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.0\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProviderBase.cs: line 93
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute(Expression expression) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v3.0\Frameworks\LLBLGen Pro\RuntimeLibraries\LinqSupportClasses\LLBLGenProProviderBase.cs: line 656
at System.Linq.Queryable.FirstOrDefault(IQueryable`1 source)
at AdventureWorks.Web.Tests._99_BugsReproduction.SelectRelatedEntity.SelectRelatedEntityIssue() in SelectRelatedEntity.cs: line 23



Wiebe Tijsma
http://www.netindustry.nl | http://www.twitter.com/wtijsma
 
Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
37879 posts
# Posted on: 10-Feb-2011 13:39:45.  
Crash happens here:
Code:

IEntityFieldCore valueField;
if(currentElement.Relation.StartEntityIsPkSide)
{
    valueField = currentRootEntity.GetFieldByName(currentElement.Relation.GetPKEntityFieldCore(j).Name);
}
else
{
    valueField = currentRootEntity.GetFieldByName(currentElement.Relation.GetFKEntityFieldCore(j).Name);
}
if(valueField.IsNull || (valueField.CurrentValue == null)) // <<<<<<<<<<<<<<<<<<<< 695


which suggests the field is null. This is impossible with generated relations. We'll see if we can repro it on adventureworks


Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
37879 posts
# Posted on: 10-Feb-2011 16:05:33.  
I can reproduce it, so I'll look into it, but there's something wrong with the query: The prefetch path is inside a wrapped query, which will automatically make it being useless. Also, you fetch a related entity which is the one being prefetched. This too makes the prefetch useless.

To fetch the related entities like they do in the above query, you don't need the prefetch path.

It would also be great if you mentioned which version they do use which works. It might help narrowing down what change might have caused this.

Fetching elements from q instead of the related entity works btw:
Code:
IQueryable<CurrencyRateEntity> q = metaData.CurrencyRate;
q = q.Where(d => d.CurrencyRateId == 1);
q = q.WithPath(a => a.Prefetch(c => c.Currency));

foreach(var v in q) { }

Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
wtijsma
User



Location:
Amsterdam
Joined on:
18-Apr-2006 15:46:26
Posted:
252 posts
# Posted on: 10-Feb-2011 16:16:08. Goto attachments  
Otis wrote:

To fetch the related entities like they do in the above query, you don't need the prefetch path.


I know, that's exactly what I mentioned in the post Regular Smiley

wtijsma wrote:
The Prefetch Path here isn't necessary (removing it fixes the problem), and the way of selecting a currency through another entity is also a bit strange, but maybe the error message can be a bit clearer if it can't be fixed.


However they have a lot of these types of constructs in their application (about 50%), including way more complex usages of these types of queries.

I've instructed them to rewrite their queries, but it's just a lot (too much) of work (and a lot of risks) for now so doesn't help them with solving other issues that actually require them to update to a new version.

I'm looking up the version number now, BRB...

Update: they sent it in attachments
Update 2: damn only 2 attachments allowed so here's the numbers:
  • DQE: 2.6.8.612
  • Linq: 2.6.8.1001
  • ORM: 2.6.8.624




Wiebe Tijsma
http://www.netindustry.nl | http://www.twitter.com/wtijsma
 
Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
37879 posts
# Posted on: 10-Feb-2011 16:16:26.  
I doubt this has ever worked. The problem is this: the prefetch path is nested in the outer query. The prefetch path is for CurrencyRate. However as the prefetch path is nested, it gets moved to the outside. However, the elements fetched there are Currency entities, not CurrencyRate entities.

The cause is the s.Currency in the wrapping query. But as you are fetching that entity, you can simply delete the prefetch path call, as it's not necessary.

It might have 'worked' in an old version which did a bad job moving the prefetch path, not sure...

(edit) the versions are very old, we had many fixes after those builds, so I can't say what caused it, other than assume the original code did a lousy job moving the prefetch path node which actually made the query 'work'. (2.6 RTM-ed on June 6th, so the version they're using is very old.

(edit) also, as they're using an old version, I doubt the queries are that complex (as older linq providers keeled over rather quickly when something looked complicated), but migrating to a later linq build will also let them run in a breaking change we had to make: projections don't append Distinct() by default anymore, which was a bug which was corrected late 2008.

I still think it's wise to fix the queries, as they will eventually have to update to a later version and the queries are wrong. It's ok to remove the prefetch path nodes in these queries, as they don't serve any purpose anyway (i.o.w.: the resultsets won't change)

It's perhaps also wise to rewrite the queries from the other side, i.e. fetch currency and filter on currencyrate, instead of the other way around, which makes things perhaps simpler in some cases.
Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
Pages: 1  


Powered by HnD ©2002-2007 Solutions Design
HnD uses LLBLGen Pro

Version: 2.1.12172008 Final.