Loading an entity values - sugestion

Jan 25, 2012 at 5:58 AM

Hy,

I want to use again in other example this OR/M. Last time it was a pleasure to work with it, so he I am again.

This time I need a sugestion.

I have one entity like this:

[TypeStorage(TableName = "postpersoana"

)] 

    

 

 

 

public class PostPersoanaEntity : Entity

{[FieldStorage(IsKey = true )]

 public int  

codpost; 

   

 

 

 

 public static string COL_CODPOST = "codpost" ;

  

[FieldStorage

]

  

 public string

marcapersoana;

 

 public static string COL_MARCAPERSOANA = "marcapersoana"



[FieldStorage

]

 

 public int

idstare;

 public static string COL_IDSTARE = "idstare"

;

 

 

........

}

The last field idstare make a relation of 1 to 1 with a entity how make corespondence between the identifier and  the name of the identifier.

[TypeStorage(TableName="starepersoana")]

 

public class StarePersoanaEntity : Entity

 

 

 

 

 

{[FieldStorage(IsKey = true)]

 

public int idstare;

 

public static string COL_IDSTARE = "idstare" ;

 

[FieldStorage

]

public string starepersoana;

public static string COL_STAREPERSOANA = "starepersoana

;

 }

Data from the two entities want to display in a grid form  like tuples:

(codpost, marcapesoana, idstare, starepersoana)

What is the best way to do this.

Thank you.

Jan 25, 2012 at 12:33 PM

Hy,

I resolved the problem above using an member in the class PostPersoanaEntity on type StarePersoanaEntity.

like this:

[ ChildStorage(ChildType = typeof(StarePersoanaEntity), LazyLoad=LazyLoadMode.On, LoadBehavior = LoadBehavior

.Select)]

 

 

 

[ ForeignKey(ParentFieldName = "idstare", ChildFieldName = "idstare"

)]

 public StarePersoanaEntity

starePersoanaEntity;

But I fight now with another problem.

I want to put into a DataGridView a collection of PostPersoanaEntity, this thing is very easy:

dgwPosturi.DataSource = persSelectata.PostPersoanaCollection;

but at runtime instead of the value of starePersoanaEntity object it displays the type name of the object.

Can u help me ?

 

 

 



Coordinator
Jan 25, 2012 at 1:34 PM
Edited Jan 25, 2012 at 1:35 PM

I understand what is happening here.

Every DataBind sample I have used (never really used Data Binding of direct Retina Entities in the UI, always used a data Service with DTOs) contained 1-n relationships, and that work well.

For 1-1 relationships, the problem is that the Binder sees the related entity just as another property (and not a collection so it can deal with it as child entities).

So far, I think you have three options:

  1. Quick & Dirty: override the ToString method in the child entity to show the fields you desire in the grid. It will not be perfect, will only show one column containing all that string, but it will work and is VERY EASY and cheap.
  2. Fool the Binder to make it think the 1-1 relationship is in reality an 1-n relationship (with only one child). Have to test it, but if the child entity would implement ICollection and always return itself as the only collection member, that should work. One caveat: the grid will not show the related entity fields as columns next to the parent columns, but you will have to "drill down" to see the children columns.
  3. Modify the Retina.NET custom Binder: Retina.Net uses a custom binder the uses Entity metadata for binding instead of just plain reflection. You can change (or enhance) that custom Binder to give child entities a special treatment (like adding the child columns to the parent's column collection, for example).

What do you think?

Andrés.

Jan 26, 2012 at 7:41 AM

Hy,

10x for the answer. U have fully understood the problem that I have.

1. The very simple and surprisingly very easy was to override to ToString() method. I put here the value that I want to show and done.

2. I try the second option. In the child class I change the type of the "collection" from ChildCollection to ICollection. The rest remained the same, but in the grid the value of the child entity was empty. I think because the method ToString() wasn't override.

3. I do not want to change anything in your clases ;). They go very well.

Jan 26, 2012 at 10:28 AM

Hy again,

I need a new suggestion for another common problem.

In the PostPersoanaEntity class I have a DateTime property:

[FieldStorage

]

 

 public DateTime

dataincadrarepost;

 

 

 public static string COL_DATAINCADRAREPOST = "dataincadrarepost"

;

  

and in the end of the class definition I put a Criteria :

 internal static Criteria ActivePost(DateTimedateCur)

{ return new Expression(typeof(PostPersoanaEntity),PostPersoanaEntity.GetField(typeof(PostPersoanaEntity), PostPersoanaEntity.COL_DATAINCADRAREPOST), CriteriaOperator.LessThanOrEqual, dateCur);

 

 

}

The question is: How can I load the PostPersoanaEntity Collection of an another entity in such way to take account of the Criteria ActivePost writen above.

Like a test now I load all PostPersoanaEntity of the entity but in the future I want to consider the Criteria ActivePost.

 This is the test now:

if (!persSelectata.PostPersoanaCollection.IsLoaded)

 

persSelectata.PostPersoanaCollection.Load(layer.Broker());

10x,

Daniel

Coordinator
Jan 26, 2012 at 12:47 PM
Edited Jan 26, 2012 at 12:48 PM

Thanks for your comments, that feature was considered some time ago but never implemented (at that time I didn't found any real usage scenario for it),

In your case, the best is to leave the unfiltered child collection being lazy loaded and then expose the dynamic Retina Expression as you did.

If there is a strong justification of this feature I can implement it. It would be something like a "DynamicFilter" property in the ChildStorage attribute, and I'm thinking that this attribute should receive a delegate returning a Criteria instance.

Having said that, messing with the loading mechanism of child collections isn't easy because there are a lot of use cases to consider and test (like inheritance and lazy loading, for example).

Best regards,

Andrés.

Jan 27, 2012 at 11:46 AM
Edited Jan 27, 2012 at 11:46 AM

Hy,

In this case is all right, because I have a few records in the ChildCollection. But when this collection is bigger it would be interesting to have the possibility to put a load filter.

So, in this case:

foreach (PostPersoanaEntity ppe in persSelectata.PostPersoanaCollection)

 if (! ppe.IsActive(DateTime 

.Now)) persSelectata.PostPersoanaCollection.Remove(ppe);

I think it's okay that way. I could make it optimally?

 

10x,

Daniel.

 

Coordinator
Jan 27, 2012 at 5:59 PM

Optimal from the performance point of view (even if that means more code and work) ?

If that's what you mean, I would suggest to avoid binding Retina entities directly and create some DTOs and some mapping process (I would recommend the awesome Automap framework).

During the loading/mapping process you manually load the child collection using whatever filter you like (doing a normal retrieve, not using Child collections) and then assigning those loaded Entities to a property of the bindable DTO class.

If you want maximum performance and control, you have to use less & less automatic loading of child collections and more & more maual loading of entities. Just a comment from my experience.

Best regards,

Andrés.