Populating Business Entities into UI

A

apoc69

hi people,

i got stucked in my project and i just dont know how to continue.
it's about puting business entities into the UI (web).

first some simple example code how an entity looks like in my project:

public class Person : Entity
{
string firstName;
string lastName;


public Person( string firstName, string lastName )
{
this.firstName = firstName;
this.lastName = lastName;
}

[EntityMemberAttribute( UINotation = "Firstname", MaxLength = 64)]
public string FirstName
{
get { return this.firstName; }
set { base.MarkDirty(); this.firstName = value; }
}

[EntityMemberAttribute( UINotation = "Lastname", MaxLength = 64)]
public string LastName
{
get { return this.lastName ; }
set { base.MarkDirty(); this.lastName = value; }
}


}


in the UI i have this code to populate that entity:


// Get all people who have an "e" in their name
EntityCollection persons =
SessionFactory.PersonSession.FindByName("e");

// Create a new webtable, set the entity collection
// as its datasource and bind
EntityWebTable webTable = new EntityWebTable();
webTable.DataSource = persons;
webTable.DataBind();



voila! an aspx page just shows me a pretty nice table, with captions (
UINotation flag in the entity ) and the persons itself ( firstname,
lastname )

ok, quite simple, isnt?

well, so far ok.. now i want to hide an field, let's say the first
name.
so i thoguht about creating an EntityView.
in that EntityView i could write something like this:

EntityView entityView = new EntityView( typeof ( Person ));
entityView["FirstName"].IsVisible = false;
webTable.DataView = entityView;


....but i dont like strong typed code like this, because if i change the
"FirstName" property in the Person entity, there wouldn't be any debug
error.

another solution would be, creating for each entity an own view. so for
the Person Entity, i would have to create a PersonView.. there i could
say:

personView.FirstName.IsVisible = false;

...but in that case, i would have to write for each entity an own view
class and if i add some new properties to an entity, i would have to
add them into the view too, and this would be pretty annoying doing
that each time. i also like to keep the "style" in the business logic (
like the notation, expressions, length );

i thought also about to change the entities itself, so if i use:
"person.FirstName" ..i would'nt get a string, i would get an object
with some other properties, something like this.

string firstName = person.firstName.Value.ToString();
bool isVisible = person.firstName.isVisible;

but personally i dont like that too..since the Value would have to be
an object, instead directly an string and this would also lead to many
many additional objects in memory.


hope somebody have some nice fresh ideas..
thanks.

steven wolf.
 
S

Scott Roberts

well, so far ok.. now i want to hide an field, let's say the first
name.
so i thoguht about creating an EntityView.
in that EntityView i could write something like this:

EntityView entityView = new EntityView( typeof ( Person ));
entityView["FirstName"].IsVisible = false;
webTable.DataView = entityView;


...but i dont like strong typed code like this, because if i change the
"FirstName" property in the Person entity, there wouldn't be any debug
error.

I don't see the point in creating an "EntityView". You've gone to the
trouble of making the collection usable by data-aware components so now use
the power of the data-aware UI component. Set the properties of the web
table to determine what columns (or fields) get displayed.

However, your concern about not finding errors if the field name is changed
is valid.
i thought also about to change the entities itself, so if i use:
"person.FirstName" ..i would'nt get a string, i would get an object
with some other properties, something like this.

string firstName = person.firstName.Value.ToString();
bool isVisible = person.firstName.isVisible;

but personally i dont like that too..since the Value would have to be
an object, instead directly an string and this would also lead to many
many additional objects in memory.

This is the approach we took. It provides many advantages to us over simple
property values (especially in the area of object persistence), but still
doesn't solve the problem you are tackling. I don't think you want to set
visibility of a field on the business object itself. That's coupling the
business object to the UI and there may be some places where firstname
should be visible and others where it should not. IMO, the business object
shouldn't care anything about visibility - that's the job of the UI.
 
T

The Crow

i can easly say that, as you evolve your design, you will see you are
implementing DataSet, and EntityTable will be a DataGrid, but one point will
be different, DataSet designed by a large team and provides solutions to
wider situations.
 
A

apoc69

hi scott,

This is the approach we took. It provides many advantages to us over simple
property values (especially in the area of object persistence), but still
doesn't solve the problem you are tackling.

tell me more about this, because i was thinking to implement this too,
but i'm still afraid that using an own object for a property (lets call
it an EntityValue) instead a simple value might lead to huge memory
consume. when a user fetch 1000 entities, and each of them have 10 own
EntityValue's and those EntityValues would have -lets say- 5 own
values, this would be:

1000 * 10 = 10.000 references
= 40 kb overhead for the EntityValue references
+ 80 kb overhead for the 10.000 EntityValue's itself
=120 kb

and then there also the values of the EntityValue...
(tell me if i calculated wrong)



i'm just afriad about this, since i also cache each fetched entity in a
"EntityCache", which leads to a very nice performance at the expense of
memory.


I don't think you want to set
visibility of a field on the business object itself. That's coupling the
business object to the UI and there may be some places where firstname
should be visible and others where it should not.

hmm right. i only want to keep the notation and the max. length in the
business logic, because this is the "language" the company talks and
have those things in one place is also nice.




@the crow:
yep, but developing an own control for this, leads to an effective way
to implement those things you realy need instead creating an
entity->dataset mapping and get satistied with the datagrid. the
problem is also, that all that stuff is not open-source, so whenever a
small change might help you, no way.


steven.
 
T

The Crow

yes, my idea about that is close to urs, but, datagrid implementation of
microsoft is very straight forward and easy, it provides all base
functionality very cleverly not more + you can add most of functionality
inheriting from that. if the case was a 3rth party component like
infragistic, i wouldnt argue with you..
and yes, im using custom entities in my project too. as i add functionality
to my entity class'es unfortunatly i see im getting close to microsoft's
datarow/dataset implementation. but having the power of strongly typed
entities, entity specific methods etc. i think im right. and because my
project is web based, i dont need most of functionality of dataset (web is
stateless so i dont need my datarows old state...) and i think i gained a
lot of performance and code readablity and compile time type checking.


BTW, does your entitytable support template columns? or readonly columns?
what will you do if you want to show negative values with red text? i bet
you will implement something like "ItemDataBound", and code it in the
codebehind. and if you need more, you will be stuck and maybe change the
whole project.
 
A

apoc69

well, we are reprogramming the whole system, which is nearly 6 years
old. the data and business layer is done, now we move to the UI, so
this entity-table is brand new. we've used datagrids before, but as
you said, we dont need the most features of a datagrid and a own
direct-solution is mostly faster and better code-readable. now for
example, we populate the content of the entities inside a javascript
array instead using thousand of <td class=data>..</td> tags, which
saves now about 40% html client output.

fortunately the whole web-ui is read-only, because the customers
sending us theire data with csv, xml, edi.. so we only need a nice
(architectual) way to put those entites into the ui.

i like to use custom attributes in the entities ( look first posting ),
so all the tables in the UI will reference to the same notation,
description etc..
but how should i tell the table: "display this and this property" with
strong typed names? (because if i want to get an property/custom
attribute, i have to write the name down)

how other people are solving that?

usualy we've used:

table.Colums.Add("Firstname");
table.Colums.Add("Lastname");

foreach ( Person person in persons )
{
TableRow row = new tableRow();
row["FirstName"] = person.FirstName;
row["LastName"] = person.LastName;
table.Rows.Add ( row );

}


....but there must be another way, instead mapping this stuff on that
way. :(

steven.
 
S

Scott Roberts

i was thinking to implement this too,
but i'm still afraid that using an own object for a property (lets call
it an EntityValue) instead a simple value might lead to huge memory
consume. when a user fetch 1000 entities, and each of them have 10 own
EntityValue's and those EntityValues would have -lets say- 5 own
values, this would be:

1000 * 10 = 10.000 references
= 40 kb overhead for the EntityValue references
+ 80 kb overhead for the 10.000 EntityValue's itself
=120 kb

and then there also the values of the EntityValue...
(tell me if i calculated wrong)



i'm just afriad about this, since i also cache each fetched entity in a
"EntityCache", which leads to a very nice performance at the expense of
memory.

Well, all I can say is that memory utilization is always a problem. The
answer depends greatly on your application and how many objects you expect
to be in memory at once and how complex those objects are. For us, having
several thousand objects in memory at once is not a problem. However, for
long-running processes that load many objects I tend to clean up memory
after every 5,000 or so just to be "safe".

I think it would be difficult to create a memory problem in a typical GUI
app (excluding long-running processes). Users rarely need to view more than
a few objects at once. In fact, showing them 10,000 search results is a
complete waste of time since no one is going to scroll through that many
anyway.

You can also "lazy load" some properties to save memory until it is actually
needed. For example, a user searches for customers and the search returns
1,000 objects. Don't load every property on all 1,000 objects, only load
those needed to display the search results. When the user selects a
particular customer, then load all info for that customer. This not only
saves memory, it keeps you from having to read so much data across the
network (from the database) only to throw it away a few seconds later.
i only want to keep the notation and the max. length in the
business logic, because this is the "language" the company talks and
have those things in one place is also nice.

We hold "class level" property information (such as max length, etc.) in
class static variables so there is only one instance per class (you don't
need a "max length" for the "FirstName" property on every object instance
since they will all be the same).
 
A

apoc69

by the way: what exactly are "data-aware ui components" ? does somebody
have a nice example for that?
 
A

apoc69

yes, we already use lazy loading and save the loaded entities in a
cache, so next time the entities are there immediality without fetching
them again from the database.

We hold "class level" property information (such as max length, etc.) in
class static variables so there is only one instance per class (you don't
need a "max length" for the "FirstName" property on every object instance
since they will all be the same).

so you have for each member of a class (e.g. firstname) a property to
get and set the firstname (person.FirstName) and a static reference to
some information about that firstname? (person.FirstNameDef.MaxLength)

tell me more if you can, because i think i have to implement something
like this, because currently i hold the max. length for example as a
custom attribute of the property:

[EntityMemberAttribute( MaxLength=64 )]
public string FirstName
{

}

but there is no way to access that attribute/information directly, only
with:
person.GetType().GetProperty("FirstName").GetCustomAttributes(....
which is pretty ugly and i have to use the exact property name in order
to get that property..
 
A

apoc69

You can also "lazy load" some properties to save memory until it is actually
needed. For example, a user searches for customers and the search returns
1,000 objects. Don't load every property on all 1,000 objects, only load
those needed to display the search results. When the user selects a
particular customer, then load all info for that customer.

are you talking about lazy-loading of (entity/domain) objects (lets say
to not load a parent company) or about lazy-loading of the person
itself, like fax and phone number?
 
S

Scott Roberts

are you talking about lazy-loading of (entity/domain) objects (lets say
to not load a parent company) or about lazy-loading of the person
itself, like fax and phone number?

Yes, both. :)
 
S

Scott Roberts

so you have for each member of a class (e.g. firstname) a property to
get and set the firstname (person.FirstName) and a static reference to
some information about that firstname? (person.FirstNameDef.MaxLength)

tell me more if you can, because i think i have to implement something
like this, because currently i hold the max. length for example as a
custom attribute of the property:

Not exactly. Each class has a public static property of type ObjectDef. The
ObjectDef has properties relating to the class itself (e.g. the table name
where the object(s) should be persisted). The ObjectDef also contains a list
of fields (FieldDef objects). The FieldDef objects contain information
related to an individual field (e.g. column name, max length, nullable,
etc.). Incidently, both ObjectDef and FieldDef information is loaded from a
database, but I suppose you could hard code them if you wanted.

Each field object (i.e. non-static field object on a particular object
intance) can find it's associated FieldDef (i.e. static field definition
held by the class) so the info is available either as static class
information (by accessing the static ObjectDef) or as meta-data on an object
instance itself.

For example, if I don't have an object instance but want the max length of
"LastName" I would type

MyClass.ObjectDef.FieldByName("LastName").MaxLength


If I have an object instance I would simply type

myObject.LastName.MaxLength


(The latter would really jut do this under the covers:
Parent.ObjectDef.FieldByName(this.FieldName).MaxLength)
 
A

apoc69

thank you soooo much!
thats actually what i will implement now,
so at last i'll be able to populate the entities like this:

Person person = new Person();

webTable.Columns.Add ( Person._Gender )
webTable.Columns.Add ( Person._FirstName )

webTable.Rows.Add ( person );



... _Gender and _FirstName are static members which also knows the
properties they are belonging to and how to invoke them, so i'll able
also to say:

string firstName = Person._FirstName.GetField ( person );

...which will return the firstName the same way as if i would say:
string firstName = person.FirstName;

("Person" is not instanced where "person" is an instance)


thank you !
steven.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top