IPredicate implementing object to add to this PredicateExpression is null.

Posts   
 
    
Darwin avatar
Darwin
User
Posts: 38
Joined: 12-Apr-2005
# Posted on: 13-Sep-2005 01:51:16   

I get this exception:

"The IPredicate implementing object to add to this PredicateExpression is null.\r\nParameter name: predicateToAdd"

From the DataAccessAdapter.FetchEntityCollection when I run this code:


CJTplateCollection templateCollection = new CJTplateCollection();
IPredicateExpression TemplatePredicateExp = new PredicateExpression();
TemplatePredicateExp.Add(PredicateFactory.CompareValue(CJTPLATEFieldIndex.CO_NUMB, ComparisonOperator.Equal, this.CO_NUMB));

RelationPredicateBucket TemplateFilter = new RelationPredicateBucket();
TemplateFilter.PredicateExpression.Add(TemplatePredicateExp);

DataAccessAdapter TemplateAdapter = new DataAccessAdapter();
TemplateAdapter.FetchEntityCollection(templateCollection, TemplateFilter);

Any ideas?

Thanks, Darwin

Paul.Lewis
User
Posts: 147
Joined: 22-Aug-2005
# Posted on: 13-Sep-2005 04:59:41   

Darwin,

Your code looks fine except for one oddity; CJTPLATEFieldIndex, shouldn't it be CJTPlateFieldIndex?

TemplatePredicateExp.Add(PredicateFactory.CompareValue(CJTPlateFieldIndex.CO_NUMB, ComparisonOperator.Equal, this.CO_NUMB));

Darwin avatar
Darwin
User
Posts: 38
Joined: 12-Apr-2005
# Posted on: 13-Sep-2005 23:06:34   

The case is correct. Classes I created based on the generated ones I changed to the "CJTplate" case. The generated code has all upper case. This compiles, and runs. It's a runtime exception that I am getting.

Thanks, Darwin

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 13-Sep-2005 23:32:17   

Could you paste a stacktrace? At first glance your code should work ok.

Frans Bouma | Lead developer LLBLGen Pro
Darwin avatar
Darwin
User
Posts: 38
Joined: 12-Apr-2005
# Posted on: 13-Sep-2005 23:58:52   

I'll get the stacktrace in a moment. Just found something strange... It only errors out when there is data (that client has templates). If there is no data that matches the criteria I get no error....

Stacktrace to come, Darwin

Darwin avatar
Darwin
User
Posts: 38
Joined: 12-Apr-2005
# Posted on: 14-Sep-2005 00:24:28   

stacktrace:

  • at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.Add(IPredicate predicateToAdd)\r\n
  • at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchEntity(IEntity2 entityToFetch, IPrefetchPath2 prefetchPath, Context contextToUse)\r\n
  • at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchEntity(IEntity2 entityToFetch, IPrefetchPath2 prefetchPath)\r\n
  • at ETConvert.CJTplate.FetchData(PrefetchPath2 Prefetch) in c:\dev\esw\data conversion\etconvert\etconvert\cjtplate.cs:line 42\r\n
  • at ETConvert.CJTplate.FetchData() in c:\dev\esw\data conversion\etconvert\etconvert\cjtplate.cs:line 37\r\n
  • at ETConvert.CJTplate..ctor(IEntityFields2 fields) in c:\dev\esw\data conversion\etconvert\etconvert\cjtplate.cs:line 30\r\n
  • at ETConvert.CJTplateFactory.Create(IEntityFields2 fields) in c:\dev\esw\data conversion\etconvert\etconvert\cjtplate.cs:line 147\r\n
  • at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.ExecuteMultiRowRetrievalQuery(IRetrievalQuery queryToExecute, IEntityFactory2 entityFactory, IEntityCollection2 collectionToFill, IFieldPersistenceInfo[] fieldsPersistenceInfo, Boolean allowDuplicates, IValidator validatorToUse)\r\n
  • at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket filterBucket, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, Int32 pageNumber, Int32 pageSize)\r\n
  • at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket filterBucket)\r\n
  • at ETConvert.Clients.LoadAndSaveDataset(String CoName) in C:\Dev\ESW\Data Conversion\ETConvert\ETConvert\Clients.cs:line 273

Here's my code from where it blows...

public virtual bool FetchData(PrefetchPath2 Prefetch)
{
    DataAccessAdapter adapter = new DataAccessAdapter();
    bool results = adapter.FetchEntity(this, Prefetch);
    return results;
}

Called by:

public virtual bool FetchData()
{
    return FetchData(this.DefaultPrefetch);
}

Called by:

public CJTplate(IEntityFields2 fields):base(fields) 
{
    this.FetchData();
}

Called by:

public override IEntity2 Create(IEntityFields2 fields)
{
    IEntity2 toReturn = new CJTplate(fields);
    return toReturn;
}

line that blows use a variable that is passed in - this.DefaultPrefetch:

protected PrefetchPath2 _DefaultPrefetch;
protected virtual PrefetchPath2 BuildDefaultPrefetch()
{
    PrefetchPath2 myDefault = new PrefetchPath2((int)EntityType.CJTPLATEEntity);
    myDefault.Add(CJTPLATEEntity.PrefetchPathJobCodeTranslate);
    return myDefault;
}
public PrefetchPath2 DefaultPrefetch
{
    get
    {
        if(_DefaultPrefetch == null)
            _DefaultPrefetch = BuildDefaultPrefetch();
        return _DefaultPrefetch;
    }
}

hmm... I'm getting some ideas from writing this out... back to testing!

Thanks, Darwin

Darwin avatar
Darwin
User
Posts: 38
Joined: 12-Apr-2005
# Posted on: 14-Sep-2005 00:39:08   

Apparently the Entity Factory is only called when the collection.count is > 0, therefore it only blows when data exists for a company... So there must be a seperate query to get the count (based on the filter), and to get the actual EntityCollection. Is that correct?

Interesting, Darwin

Darwin avatar
Darwin
User
Posts: 38
Joined: 12-Apr-2005
# Posted on: 14-Sep-2005 00:46:42   

It's in the Default.Prefetch that the problem exists. I don't know where or what... I changed the offending line to not use the DefaultPrefetch and it works. I do need the prefetch data so any help to make it work INCLUDING the prefetch data would be great.

Thanks, Darwin

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 14-Sep-2005 10:16:43   

I'm still looking at it, though I have a question about this:

at ETConvert.CJTplate.FetchData() in c:\dev\esw\data conversion\etconvert\etconvert\cjtplate.cs:line 37\r\n

at ETConvert.CJTplate..ctor(IEntityFields2 fields) in c:\dev\esw\data

how does the constructor end up in fetch data?

(edit). Ok, here's the deal: the fetch you start with the prefetch path, first tries to fetch the entity with a pk filter. Apparently this entity doesn't have pk fields set, probably because you call the fetch before the fields are set in the entity. Because of this, there is no PK filter. A prefetch path filter uses the filter of the parent (in this case the pk filter) to fetch the entities in the current prefetch path node. As there's no filter, it adds null to the filter to use for the path fetch, which thus fails.

Frans Bouma | Lead developer LLBLGen Pro
Darwin avatar
Darwin
User
Posts: 38
Joined: 12-Apr-2005
# Posted on: 14-Sep-2005 18:16:02   

CJTplate has no primary key. Bottom line is if you have no PK you cannot use a prefetch. Is this correct?

Thanks, Darwin

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 14-Sep-2005 19:23:47   

Darwin wrote:

CJTplate has no primary key. Bottom line is if you have no PK you cannot use a prefetch. Is this correct?

Thanks, Darwin

Not in single entity fetches. In collection fetches you can of course, but in single entity fetches you can't. Single entity fetches without a pk is not possible anyway (or you should use a unique constraint). Is this the case, do you use a unique constraint?

Frans Bouma | Lead developer LLBLGen Pro
Darwin avatar
Darwin
User
Posts: 38
Joined: 12-Apr-2005
# Posted on: 14-Sep-2005 20:30:39   

This is a collection fetch. It appears (from the stack trace) that the collection is populated by calling the entity fetch for each of the entities in the collection. I am fetching the collection of templates for a company (by co_numb). I never intended to fetch the templates individually.

I found a way to work around this, so I can let it go. Interesting learning more about collections and how they work under the hood a bit though.

Thanks, Darwin

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 15-Sep-2005 11:01:31   

Darwin wrote:

This is a collection fetch. It appears (from the stack trace) that the collection is populated by calling the entity fetch for each of the entities in the collection. I am fetching the collection of templates for a company (by co_numb). I never intended to fetch the templates individually.

Though that's what's going on indeed, because you initiate the fetch from the object constructor (or methods called by the constructor). simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Darwin avatar
Darwin
User
Posts: 38
Joined: 12-Apr-2005
# Posted on: 15-Sep-2005 18:48:35   

At one time (a long time ago) I did not have the fetch inside my constructor and I was getting no data in my collections. I assumed that you need to have the fetch in the constructor to get data in your collection. Is there a better way?

Let me know, Darwin

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 15-Sep-2005 19:17:44   

you mean to fill the child collection? With a prefetch path while fetching the parent, or fetching the child collection separately. Though I'm not sure if I understand the situation/question correctly.

Frans Bouma | Lead developer LLBLGen Pro