string references for objects

Posts   
 
    
jovball
User
Posts: 435
Joined: 23-Jan-2005
# Posted on: 31-Oct-2005 16:58:39   

I'm working on some dynamic reporting tasks and wondering if there is a way to instantiate/reference LLBLGen TypedViews and/or fieldindex values from a string value.

Psuedo-code would look something like this:


Dim da As New DataAccessAdapter
Dim bucket As New RelationPredicateBucket
Dim filter As New PredicateExpression
Dim dt As New DataTable

'instantiate a class using the name (string)
Dim view As New TypedView("CustomerOrders")

'get the field index, again by using the name(string)
filter.Add(PredicateFactory.CompareNull(view("ShippedDate"))
bucket.PredicateExpression.Add(filter)

da.FetchTypedView(view.GetFieldsInfo(), dt, bucket)

Joel Reinford Data Management Solutions LLC

tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 31-Oct-2005 19:06:05   

jovball wrote:

I'm working on some dynamic reporting tasks and wondering if there is a way to instantiate/reference LLBLGen TypedViews and/or fieldindex values from a string value.

Psuedo-code would look something like this:


Dim da As New DataAccessAdapter
Dim bucket As New RelationPredicateBucket
Dim filter As New PredicateExpression
Dim dt As New DataTable

'instantiate a class using the name (string)
Dim view As New TypedView("CustomerOrders")

'get the field index, again by using the name(string)
filter.Add(PredicateFactory.CompareNull(view("ShippedDate"))
bucket.PredicateExpression.Add(filter)

da.FetchTypedView(view.GetFieldsInfo(), dt, bucket)

Joel Reinford Data Management Solutions LLC

You could try using reflection to do this. We do this a lot in our project as entity types are loaded dynamically from a string at run time.

jovball
User
Posts: 435
Joined: 23-Jan-2005
# Posted on: 31-Oct-2005 23:36:15   

Can you give me a short example using reflection and LLBLGen? A little push in the right direction would be nice ...

Joel Reinford Data Management Solutions LLC

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 31-Oct-2005 23:47:03   

jovball wrote:

Can you give me a short example using reflection and LLBLGen? A little push in the right direction would be nice ...

Joel Reinford Data Management Solutions LLC

Have you tried Activator.CreateInstance(typenameAsString); ?

You've to specify the type name and the Activator class (part of .NET) will create a new instance for you.

Frans Bouma | Lead developer LLBLGen Pro
jovball
User
Posts: 435
Joined: 23-Jan-2005
# Posted on: 04-Nov-2005 06:10:00   

I have the first part of this figured out but need some help with the rest. The code below works just fine and creates a typedview from a string parameter. Now I'm trying to figure out how to do the FieldIndex parameters from a string parameter.


Dim dllName As String
Dim viewName As String
    
Dim view As ITypedView2
Dim sortOrder As ISortExpression = New SortExpression
Dim bucket As New RelationPredicateBucket
Dim filter As New PredicateExpression
        
Dim da As New DataAccessAdapter
Dim dt As New DataTable

dllName = "northwind.dal"
viewName = dllName & ".TypedViewClasses." & "AlphabeticalListOfProductsTypedView"

view = DirectCast(Activator.CreateInstance(dllName, viewName).Unwrap, ITypedView2)


With filter
                .Add(PredicateFactory.CompareValue(AlphabeticalListOfProductsFieldIndex.CategoryId, ComparisonOperator.Equal, 2))
                .AddWithAnd(PredicateFactory.CompareValue(AlphabeticalListOfProductsFieldIndex.UnitPrice, ComparisonOperator.GreaterEqual, 10))
End With
bucket.PredicateExpression.Add(filter)

With sortOrder
            .Add(SortClauseFactory.Create(AlphabeticalListOfProductsFieldIndex.ProductName, SortOperator.Ascending))
End With

da.FetchTypedView(view.GetFieldsInfo(), dt, bucket, 0, sortOrder, True)


What I want to do is to create SomeFieldIndex.SomeEnumValue based on a string parameter. For example, convert a string input of "AlphabeticalListOfProductsFieldIndex.CategoryId" into an enum object of AlphabeticalListOfProductsFieldIndex.CategoryId.

Joel Reinford Data Management Solutions LLC

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 04-Nov-2005 10:48:59   

What I want to do is to create SomeFieldIndex.SomeEnumValue based on a string parameter. For example, convert a string input of "AlphabeticalListOfProductsFieldIndex.CategoryId" into an enum object of AlphabeticalListOfProductsFieldIndex.CategoryId.

You can use teh System.Enum static methods for that I think, to produce a new enum value.

Frans Bouma | Lead developer LLBLGen Pro
Prabha
User
Posts: 8
Joined: 28-Feb-2007
# Posted on: 02-Mar-2007 05:54:29   

I am feeling difficult to convert string "AlphabeticalListOfProductsFieldIndex.CategoryId" to an enum object.can anyone help me to achive this.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 02-Mar-2007 12:24:45   

You have to pass in CategoryId as value to Enum.Parse, together with the type of the enum. Though you normally won't have to do this, so it's best to describe why you want to use this first.

Frans Bouma | Lead developer LLBLGen Pro
Prabha
User
Posts: 8
Joined: 28-Feb-2007
# Posted on: 06-Mar-2007 06:16:31   

I am doing an dynamic report generation.So at runtime only i will have the view name and its fields. To make the predicate bucket i have written the code(for wxample) like:


dllName = "northwind.dal"
Dim sViewname As String = "dllName.TypedViewClasses.AlphabeticalListOfProductsTypedView"
Dim sFieldName As String = "CategoryId"
Dim assembly_name As AssemblyName = New AssemblyName
assembly_name.CodeBase = dllName 
Dim assemble As [Assembly] = AppDomain.CurrentDomain.Load(assembly_name)
Dim enumType As Type = assemble.GetType(sViewname)
Dim enumItem As FieldInfo = enumType.GetField(sFieldName)

to specify this in the predicate bucket:


 Dim BKT As New RelationPredicateBucket
 BKT.PredicateExpression.Add(PredicateFactory.CompareValue(enumType.enumItem, ComparisonOperator.GreaterEqual, 0))

if i use like this i am getting an compilation error: Overload resolution failed because no accessible CompareValue can be called without a narrowing conversion.

am i moving in a correct way?....

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 06-Mar-2007 06:28:26   

Instead of: Dim sViewname As String = "dllName.TypedViewClasses.AlphabeticalListOfProductsTypedView"

Try this: Dim sViewname As String = "AlphabeticalListOfProductsTypedViewFieldIndex"

Prabha
User
Posts: 8
Joined: 28-Feb-2007
# Posted on: 06-Mar-2007 07:18:21   

Thanks for immediate reply walla but still i am getting an error

This is my code:


dllName = "northwind.dal"
Dim sViewname As String = "AlphabeticalListOfProductsTypedViewFieldIndex"
Dim sFieldName As String = "CategoryId"
Dim assembly_name As AssemblyName = New AssemblyName
assembly_name.CodeBase = dllName 
Dim assemble As [Assembly] = AppDomain.CurrentDomain.Load(assembly_name)
Dim enumType As Type = assemble.GetType(sViewname)
Dim enumItem As FieldInfo = enumType.GetField(sFieldName)

Dim BKT As New RelationPredicateBucket
Dim DA As New DataAccessAdapter
Dim INV_DETAILS As New SND_TTB_INVOICE_TAX_HEADEREntity
Dim DT_DATA As New DataTable
[b]BKT.PredicateExpression.Add(PredicateFactory.CompareValue(enumType.GetField(sFieldName), ComparisonOperator.Equal, 0))[/b]


Now i am getting:

Overload resolution failed because no accessible 'CompareValue' can be called with these arguments: ....it is showing a long possible arguments....

You got any other idea?...

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 06-Mar-2007 08:18:13   

Please post the complete error text. Most probably you are using a wrong overload of the CompareValue method. Note that there are overloads to be used for SelfServicing and some are used for the Adapter model.

Prabha
User
Posts: 8
Joined: 28-Feb-2007
# Posted on: 06-Mar-2007 11:27:22   

It is saying that 'System.Reflection.FieldInfo' cannot be converted to 'AlphabeticalListOfProductsTypedViewFieldIndex'.

Error:

Overload resolution failed because no accessible 'CompareValue' can be called with these arguments: 'Public Shared Function CompareValue(indexOfField As AlphabeticalListOfProductsTypedViewFieldIndex, operatorToUse As SD.LLBLGen.Pro.ORMSupportClasses.ComparisonOperator, value As Object) As SD.LLBLGen.Pro.ORMSupportClasses.FieldCompareValuePredicate': Value of type 'System.Reflection.FieldInfo' cannot be converted to 'AlphabeticalListOfProductsTypedViewFieldIndex'.

Aurelien avatar
Aurelien
Support Team
Posts: 162
Joined: 28-Jun-2006
# Posted on: 06-Mar-2007 15:57:26   

Hi,

enumType.GetField(sFieldName)

return a System.Reflection.FieldInfo, which can't be converted to AlphabeticalListOfProductsTypedViewFieldIndex.

You can try :

enumType.GetField(sFieldName).GetValue(Nothing)

instead, but 'im not sure it will work. It works with static members only, I guess an enum member is static...

Jessynoo avatar
Jessynoo
Support Team
Posts: 296
Joined: 19-Aug-2004
# Posted on: 06-Mar-2007 16:32:17   

Hi,

I think you are mixing several things there.

Fields are embedded accross 3 types of objects:

First you've got the properties generated by LLBLGen in the concrete classes:

That's what you're trying to access when using:

Dim enumItem As FieldInfo = enumType.GetField(sFieldName)

In your sample, you're getting a reference to the "CategoryId" property, of type Integer I guess.

Now if you look what's inside the getter, you'll see there's no _CategoryId private member as you may expect but instead it accesses an element of a collection of type EntityFields2, thus an item of type EntityField2, which is some kind of LLBLGen descriptor for your columns.

It exposes various information though several properties, combining the format of the targetted column (this is actually split into a dbgeneric (IEntityCore) and a dbspecific (IFieldPersistenceInfo) side) and also the value and state of that field in the current entity/typedview the field belongs to.

Now in other terms, yourCategory.CategoryId is a shortcut for yourCategory.Fields["CategoryId"].CurrentValue

And finally, in order to ease various accesses to the fields, some Enumeration were generated for each entity/view: the fields are enumerated with their names and integer values as their order of their use in corresponding EntityFields collection. AlphabeticalListOfProductsFieldIndex.CategoryId is an example.

So once again that is 3 different types and you have:

yourCategory.CategoryId ~ yourCategory.Fields["CategoryId"].CurrentValue = yourCategory.Fields[0].CurrentValue = yourCategory.Fields[(int) AlphabeticalListOfProductsFieldIndex.CategoryId].CurrentValue

Now, as for the use of those 3 faces of the same data, their are several ways leading to the same path.

The generated predicate factories take enums values as inputs, because they call EntityFields factories to produce the EntityFields from their enums but you may also use the EntityFields directly.

PredicateFactory.CompareValue(AlphabeticalListOfProductsFieldIndex.CategoryId, ComparisonOperator.Equal, 2) is the same as:

(FieldCompareByValuePredicate) (AlphabeticalListOfProductsFields.CategoryId = 2)

Here, AlphabeticalListOfProductsFields.CategoryId is not the enum but rather a property of an helper class providing a shortcut to the EntityField factory.

That said you have to correct the mix between:

System.Reflection.FieldInfo extracted by reflection from the corresponding CategoryId AlphabeticalListOfProductsTypedView property

SD.LLBLGen.Pro.ORMSupportClasses.EntityField2 that you can obtain from

EntityFieldFactory.Create(AlphabeticalListOfProductsFieldIndex.CategoryId) or equivalently AlphabeticalListOfProductsFields.CategoryId or also yourCategory.Fields["CategoryId"]

and finally the enum AlphabeticalListOfProductsFieldIndex.CategoryId

Hope that makes it clearer Cheers

Prabha
User
Posts: 8
Joined: 28-Feb-2007
# Posted on: 07-Mar-2007 11:19:56   

Thanks Aurelien

Its working fine, but it is taking to much of time to set the filter bucket and execute.

luciusism
User
Posts: 119
Joined: 02-Jun-2007
# Posted on: 09-Mar-2008 00:43:03   

I had a similar situation. I wanted to get EntityField2 objects into my predicate statements based on a passed field string as defined from a DropDownList control.

Doing this is pretty simple with an entity seeing as it has the Fields collection to enumerate. For typedViews, I did the following using reflection:


public static EntityField2 GetTypedViewField(string field, Type type)
{
    EntityField2 fieldToReturn = null;
    try
    {
        System.Reflection.PropertyInfo[] properties = type.GetProperties();
        foreach (System.Reflection.PropertyInfo p in properties)
        {
            if (p.Name == field)
            {
                fieldToReturn = (EntityField2)p.GetValue(null, null);
                break;
            }
        }
    }
    catch (Exception ex)
    {
        Utilities.ErrorLog("65edsfseafwa45", ex);
    }

    return fieldToReturn;
}


The above would then be used in such a context:


bucket.PredicateExpression.Add(GetTypedViewField(field, typeof(CustomerTypedViewFields)) == searchKeyword );

Of course, for something more robust, you'd want to see Frans' post here: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=332