External query condition

Posts   
 
    
orenpeled
User
Posts: 53
Joined: 25-Jul-2005
# Posted on: 24-Aug-2005 13:09:05   

Hi,

I have an application that creates new tables at runtime, so using LLBLGen for those table is impossible. However, I do use LLBLGen for my predefined tables. My problem is, that I want to perform queries that involve both my predefined tables and my dynamic tables. It is a crime not to use the LLBLGen mechanism for queries, and I need to know if there is any way to combine my external conditions (relates to the dynamic tables) with the strong-typed conditions (using a filter-bucket - relates to the predefined tables), say, by concatenating strings or something like that

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 25-Aug-2005 09:46:53   

The query mechanism is build around field objects (EntityField for selfservicing, EntityField2 for adapter). You can create these in code, like the generated code does too (see EntityFieldFactory and in adapter for example the PersistenceInfoFactory )

Then, you can use such field objects in Field*Predicate instances, for example to compare a field to a value, you can create a FieldCompareValuePredicate, passing in an EntityField object you created. Similarly with relations. (take a look in one of the Relations classes in the generated code).

I'm not sure if there is some kind of pattern in your dynamic created tables/fields, but likely there is. You can utilize that pattern to create some kind of factory class for your dynamic entityfields. If you're using adapter, it's required the persistenceinfofactory is adjusted so the persistenceinfo for your dynamic table targeting fields is retrievable. This can be done with a custom template.

Frans Bouma | Lead developer LLBLGen Pro
takb
User
Posts: 150
Joined: 12-Mar-2004
# Posted on: 07-Nov-2005 13:09:48   

I'm wanting to do the something similar - that is filter and join on fields and tables that are created at runtime. I'm using 1.0.2005.1 and Adapter and have done the following:

  • Created an ExtensionField entity derived from EntityField2
  • I have a routine which adds extension fields to my dynamically created lists. It creates instances of the ExtensionField entities and adds them to the list after doing a Fields.Expand.
  • In our custom DataAccessAdapter, I've overridden GetFieldPersistenceInfo to do the following:
        protected override IFieldPersistenceInfo GetFieldPersistenceInfo(IEntityField2 field)
        {
            if(field is ExtensionField)
            {
                return (field as ExtensionField).GetFieldPersistenceInfo();
            }
            else
            {
                return base.GetFieldPersistenceInfo(field);
            }
        }
  • The ExtensionField.GetFieldPersistenceInfo returns the appropriate IFieldPersistenceInfo object.

So far so good.

But now I want to add the table that the extension field appears in to my lists relation collection. Part of the "Add Extension Fields" routine adds appropriate relations. I've copied some code from the generated code to do this...and I thought I had it pretty right using code like:

    relation1 = new EntityRelation(RelationType.OneToOne);
    relation1.AddEntityFieldPair(EntityFieldFactory.Create(DOCUMENTBASEFieldIndex.ID), 
    CreateIDEntityField(documentExtension.TABLENAME, "DOCUMENTBASEID"));
    relation1.StartEntityIsPkSide = false;
    relation1.InheritanceInfoPkSideEntity = InheritanceInfoProviderSingleton.GetInstance().GetInheritanceInfo("DOCUMENTBASEEntity", false);
    relation1.InheritanceInfoFkSideEntity = InheritanceInfoProviderSingleton.GetInstance().GetInheritanceInfo(documentExtension.TABLENAME, true);

All seems ok, but when I do my adapter.FetchTypedList, I get an exception:

 System.NullReferenceException : Object reference not set to an instance of an object.
    at SD.LLBLGen.Pro.ORMSupportClasses.InheritanceInfoProviderBase.GetHierarchyRelations(ArrayList entityNames)
    at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchTypedList(IEntityFields2 fieldCollectionToFetch, DataTable dataTableToFill, IRelationPredicateBucket filterBucket, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize)
    at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchTypedList(IEntityFields2 fieldCollectionToFetch, DataTable dataTableToFill, IRelationPredicateBucket filterBucket)

My extension fields and tables aren't in an inheritance relationship with my base table, however since for all generated relations there is code to set the InheritanceInfo, I assume that this is needed. (I also get the same exception if I don't set the InheritanceInfo properties). Any ideas what I'm missing which is causing this exception? I think I'm missing something defining the "Entity" since the GetHierarchyRelations call gets passed an ArrayList of entityNames.

takb
User
Posts: 150
Joined: 12-Mar-2004
# Posted on: 08-Nov-2005 08:14:36   

Ok, it was me.

While I was testing I didn't want to bother with filtering and just wanted all results from my query so I passed a null for the filterBucket of FetchTypedList. That caused it to go through the inheritance code and fail because _entityToPathToRoot had no elements so the following code in InheritanceInfoProviderBase.GetHierarchyRelations(ArrayList entityNames) failed on pathToRoot.Count because pathToRoot is null:


                ArrayList pathToRoot = (ArrayList)_entityToPathToRoot[entityName];
                if(pathToRoot.Count> longestPath.Count)

Anyway, add a proper filter bucket and now I can use my dynamically generated tables! Bewdy!