Create IEntityRelation with reflection.

Posts   
 
    
tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 01-Jul-2005 02:16:53   

Can anyone show me how to create a relation using reflection. I need this becaue I am currently creating and fetching an entity collection and prefetch paths with reflection and now need to add relations and a sort expression.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 01-Jul-2005 09:48:32   

You mean, you want, via reflection, call someEntity.Relations.SomeRelation... ?

You can also create an EntityRelation in code, without reflection.

Just curious: why you need reflection to fetch a collection/creating a prefetchpath?

Frans Bouma | Lead developer LLBLGen Pro
tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 01-Jul-2005 20:07:36   

Otis wrote:

You mean, you want, via reflection, call someEntity.Relations.SomeRelation... ?

You can also create an EntityRelation in code, without reflection.

Just curious: why you need reflection to fetch a collection/creating a prefetchpath?

This is a method that was written for my by another developer and I am now trying to extend its functionality. What I am trying to do is move the sorting from entityProductVersionFetchPath to the adapter.FetchEntityCollection method and add sorting on two more fields. Now I believe that I need to create relations between the tables for the sort to work an exception will thrown stating that "The column prefix 'dbname.dbo.tablename' does nat match...". So I am now trying to create a relation based on the entityClass variable and was trying to use code similer to how the prefetch path entityProductFetchPath and can't make it work. Does this help?


public EntityCollection Execute() {
            Assembly assembly = Assembly.GetAssembly(typeof(ProductEntity));
            Type factoryType = assembly.GetType("WrenchScience.LLBLGen.FactoryClasses." + entityClass.Name + "Factory");
            IEntityFactory2 factory = (IEntityFactory2)factoryType.GetConstructor(new Type[0]).Invoke(new object[0]);
            EntityCollection products = new EntityCollection(factory);

            EntityType entityType = (EntityType)Enum.Parse(typeof(EntityType), !entityClass.Name.StartsWith("My") ? entityClass.Name : entityClass.Name.Substring(2) /* skip "My" */);
            
            IPrefetchPathElement2 entityProductFetchPath = (IPrefetchPathElement2)entityClass.GetProperty("PrefetchPathProduct").GetValue(null, new object[0]);
            //IPrefetchPathElement2 entityManufacturerFetchPath = (IPrefetchPathElement2)entityClass.GetProperty("PrefetchPathManufacturer").GetGetMethod().Invoke(null, new object[0]);
            IPrefetchPathElement2 entityProductVersionFetchPath = (IPrefetchPathElement2)entityClass.GetProperty("PrefetchPathProductVersion").GetValue(null, new object[0]);
            
            ISortExpression sort = new SortExpression();
            //sort.Add( SortClauseFactory.Create(ProductFieldIndex.ManufacturerID, SortOperator.Ascending) );
            //sort.Add( SortClauseFactory.Create(ProductFieldIndex.Model, SortOperator.Ascending) );
            sort.Add( SortClauseFactory.Create(ProductVersionFieldIndex.RPPrice, SortOperator.Ascending) );
            sort.Add( SortClauseFactory.Create(ProductVersionFieldIndex.MfrGrams, SortOperator.Ascending) );

            IPrefetchPath2 prefetchPath = new PrefetchPath2((int)entityType);
            IPrefetchPathElement2 productNode = prefetchPath.Add(entityProductFetchPath);
            IPrefetchPathElement2 manufacturerNode = productNode.SubPath.Add(ProductEntity.PrefetchPathManufacturer);
            manufacturerNode.SubPath.Add(MyManufacturerEntity.PrefetchPathCompany);
            prefetchPath.Add(entityProductVersionFetchPath, 1, null, null, sort);

            filter = new RelationPredicateBucket();
            //filter.Relations.Add(ProductVersionEntity.Relations.ProductEntityUsingProductID);
            //IRelationCollection relations = (IRelationCollection)entityClass.GetProperty("Relations").GetValue(null, new object[0]);
            //IEntityRelation relation = (IEntityRelation)entityClass.GetProperty("Relations").GetValue(null, new object[0]);
            //filter.Relations.Add(relation);
            //filter.Relations.Add(BrakeEntity.Relations.ProductVersionEntityUsingProductVersionID);
            
            foreach (ICriteria criteria in criterias) {
                IPredicate expression = criteria.CreatePredicateExpression(logicManager, this);
                if (expression != null)
                    filter.PredicateExpression.Add(expression);
            }
            
            DataAccessAdapter adapter = new DataAccessAdapter();
            adapter.FetchEntityCollection(products, filter, prefetchPath);

            return products;            
        }

tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 01-Jul-2005 21:09:12   

Here is an update that I made and that now seems to create a entity.Relations class. Now I get the error "System.Reflection.TargetException: Non-static method requires a target" on the last line. Now I am seeing that the property Relations is static which probably has something to do with my problem, but I don't know what to do.


filter = new RelationPredicateBucket();
filter.Relations.Add(ProductVersionEntity.Relations.ProductEntityUsingProductID);
object relations = entityClass.BaseType.GetProperty("Relations").GetValue(null, new object[0]);
IEntityRelation relation = (IEntityRelation)relations.GetType().GetProperty("ProductVersionEntityUsingProductVersionID").GetValue(null, new object[0]);

What I am trying create is this:


filter.Relations.Add(BrakeEntity.Relations.ProductVersionEntityUsingProductVersionID);

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 02-Jul-2005 10:50:13   

I think it's better to create an instance of the BrakeRelations class and then call via reflection the property ProductVersionEntityUsingProductVersionID.

After all, all BrakeEntity.Relations does is create an instance of BrakeRelations.

Is there a particular reason why this call isn't programmed hardcoded in your code?

Frans Bouma | Lead developer LLBLGen Pro
tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 05-Jul-2005 19:56:32   

Otis wrote:

I think it's better to create an instance of the BrakeRelations class and then call via reflection the property ProductVersionEntityUsingProductVersionID.

After all, all BrakeEntity.Relations does is create an instance of BrakeRelations.

Is there a particular reason why this call isn't programmed hardcoded in your code?

The reason why this isn't hard coded is that the class BrakeRelations could be FrameRelations or ForkRelations or some other part. The Product table and ProductVersion table are assocated to a bunch of product specific tables and so I need to dynamically create the relation based on the current table being used.

This code seems to correctly create an instance of BrakeRelations and I am now trying to figure out how to create the relation using the next bit of code.


// Create Relations object.
Type relationType = assembly.GetType("WrenchScience.LLBLGen.RelationClasses." + entityName + "Relations");
object relations = relationType.GetConstructor(new Type[0]).Invoke(new object[0]);
// Create relation.
IEntityRelation relation = (IEntityRelation)relations.GetType().GetProperty("ProductVersionEntityUsingProductVersionID").GetValue(null, new object[0]);

The last line of code here is still throwing the exception "System.Reflection.TargetException: Non-static method requires a target.". Do you have any idea what I am doing wrong?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 05-Jul-2005 21:11:41   

I think you should do:


IEntityRelation relation = (IEntityRelation)relationType.GetProperty("ProductVersionEntityUsingProductVersionID").GetValue(relations, new object[0]);

The type you already have and you have to pass in the instance you want to call the GetValue on, which is 'relations' simple_smile

Frans Bouma | Lead developer LLBLGen Pro
tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 06-Jul-2005 00:24:04   

Otis wrote:

I think you should do:


IEntityRelation relation = (IEntityRelation)relationType.GetProperty("ProductVersionEntityUsingProductVersionID").GetValue(relations, new object[0]);

The type you already have and you have to pass in the instance you want to call the GetValue on, which is 'relations' simple_smile

Otis,

Thank you for the help. I now have this working, this was exactly what I needed.