Adding Field to TypedList

Posts   
 
    
ScottCate
User
Posts: 48
Joined: 11-May-2005
# Posted on: 26-Nov-2005 23:54:37   

I have an entity that I'm using to fetch a typedlist. I'm trying to programmatically add a relationship and a column. I've added the relationship file, but I can't figure out how to add the column (fields).

Essentially I'm looking for something like this.

Entity is IEntity2; field is IEntityField2;


Entity.Fields.Add(field)

But that fails. So I found the .Expand method off of EntityFields2, but it only takes an int, and I couldn't figure out how to actually add the field to the array, because it's hidden, so I wrote this overloaded method.


/// <summary>
/// Expands this entity fields object by 1, and appending field to this object. 
/// </summary>
/// <param name="field">field to append to this fieldsobject</param>
/// <remarks>Use with care. Empty cells can cause the DQE's to produce undefined results. Use this routine to append fields to a
/// Typed list in code for example. </remarks>
public void Expand(IEntityField2 field)
{
    IEntityField2[] newFieldsInstance = new EntityField2[_entityFields.Length + 1];
    _entityFields.CopyTo(newFieldsInstance, 0);
    newFieldsInstance[newFieldsInstance.Length] = field;
    _entityFields = newFieldsInstance;
}

Which works great. So I thought I was home free.

My plan was to ...


Entity.Fields.Expand(field);

But that fails becuase Entity.Fields is of type IEntityFields2, not IEntityField2 (see the field vs. fields) so again, i'm stuck.

In a perfect world, the CTOR of ResultsetFields would take an IEntityFields2, or IEntityFieldCore[] object.

I'm obviously missing something.

So the typedlist should return all the columns of Entity + 1, through the relationship. I know the relation is working because I used SQL Profiler, and I can see the correct T-SQL getting to the Server. Now to just add that extra field definition.

Thanks for your help.

ScottCate
User
Posts: 48
Joined: 11-May-2005
# Posted on: 28-Nov-2005 05:49:41   

Hey Otis,

Any help on this, I know it's the weekend and all. flushed

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 28-Nov-2005 10:46:02   

Expand receives the # of extra fields you want to add. EntityFields(2) uses internally an array. So you should call: Expand(1), and then call Add(field)

Frans Bouma | Lead developer LLBLGen Pro
ScottCate
User
Posts: 48
Joined: 11-May-2005
# Posted on: 28-Nov-2005 13:38:36   

I 100% agree with you.

My underlining question is how to get the original ReseltSetFields from myEntity.Fields?

Do I have to loop thought myEntity.Fields and Create the ResultSetFields one by one?

This is what I was trying to avoid, since the full array is already populated, why shuould I have to re-create it?

-=- Scott Cate

ScottCate
User
Posts: 48
Joined: 11-May-2005
# Posted on: 28-Nov-2005 16:09:35   

Here's a working solution. Please confirm if you think this is good/bad/helpful.

I added an overload to EntityField2.Expand(int numberOfNewCells) as follows.

/// <summary>
/// Expands this entity fields object by 1, and appending field to this object. 
/// </summary>
/// <param name="field">field to append to this fieldsobject</param>
/// <remarks>Use with care. Empty cells can cause the DQE's to produce undefined results. Use this routine to append fields to a
/// Typed list in code for example. </remarks>
public void Expand(IEntityField2 field)
{
    IEntityField2[] newFieldsInstance = new EntityField2[_entityFields.Length + 1];
    _entityFields.CopyTo(newFieldsInstance, 0);
    newFieldsInstance[newFieldsInstance.Length-1] = field;
    _entityFields = newFieldsInstance;
}

This is the only way I could figure out how to add the new entity. There is an .Expand method, but no add method. I suppose (now that i'm tryping this), I could just do something like

dynamicFields.Expand(1);
dynamicFields[dynamicFields.Count-1] = EntityFieldFactory.Create(MyEntityFieldIndex.FieldName); 

That is better, since I wouldn't have to modify the Engine Code, but if you like it, would you please consider adding the above overload in a future version?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 29-Nov-2005 10:58:24   

ScottCate wrote:

I 100% agree with you. My underlining question is how to get the original ReseltSetFields from myEntity.Fields? Do I have to loop thought myEntity.Fields and Create the ResultSetFields one by one?

No, you don't have to. ResultsetFields is a derived class from EntityFields2, and myEntity is an EntityFields2 object, which thus makes both implement IEntityFields2, the interface the runtime code works with. ResultsetFields is a class with typed methods so it's easier to add a field.

So you can just do: myEntity.Fields.Expand(1); myEntity.Fields.Add(myField);

or similar, it's the same. simple_smile

Though could you paste the code you use to fetch the data? I'm a bit lost what exactly you're trying to do. Do you want to add a field to an existing typed list at runtime or do you want to fetch a dynamic list using the fields of an entity ?

Frans Bouma | Lead developer LLBLGen Pro
ScottCate
User
Posts: 48
Joined: 11-May-2005
# Posted on: 29-Nov-2005 17:53:27   

Otis wrote:

So you can just do: myEntity.Fields.Expand(1); myEntity.Fields.Add(myField);

or similar, it's the same. simple_smile

That Code is not valid, becuase I'm using interfaces. This is info that I didn't pass in before. Probably would have cleared up a lot to say that historyEntity is being passed into this method as IEntity2. Basically Every HistoryEntity (my audit system) has an OperatorId, and I want to create a link to the user table.

IEntity2.Fields is of type IEntityFields2 which does not have a definition for Expand();

If I were not using interfaces, and I acutally had the full EntityFields2, then I'd have the Expand method, but my "historyEntity" is being passed in as an interface IEntity2.

Add the relationship

 //add relation to OperatorId
IEntityRelation relation = new EntityRelation(RelationType.OneToOne);
relation.StartEntityIsPkSide = false;
IEntityField2 OperatorField = 
    new EntityField2("OperatorId", histEntity.LLBLGenProEntityName, 
    typeof(System.Guid), TypeDefaultValue.GetDefaultValue(typeof(System.Guid)),
    false, OperatorFieldIndex, 0, 0, 0, false, false, false);
relation.AddEntityFieldPair(EntityFieldFactory.Create(UserFieldIndex.UserId),OperatorField);
filter.Relations.Add(relation);

And then to add the Login Name, I have to ....

 //Build Fields
EntityFields2 dynamicFields = new EntityFields2(histEntity.Fields.Count);
for (int i = 0; i < dynamicFields.Count; i++)
{
    dynamicFields[i] = histEntity.Fields[i];
}

//Build Operator LoginName field
IEntityField2 OperatorLoginName = EntityFieldFactory.Create(UserFieldIndex.LoginName);
dynamicFields.Expand(1);
dynamicFields[dynamicFields.Count-1] = OperatorLoginName;

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 30-Nov-2005 13:45:18   

Ok I see what you mean. All Adapter entities (of IEntity2) have an entity fields object of type EntityFields2. I see the methods I proposed aren't present in the interface which is an oversight from my part. I'll correct that in the next version.

You can also instantiate a new EntityFields2 object like this: EntityFields2 newFields = new EntityFields2(myEntity.Fields.GetAsEntityFieldCoreArray());

then, call expand and add the field. You can also cast to EntityFields2, as all entities have EntityFields2 objects as their field objects.

Frans Bouma | Lead developer LLBLGen Pro