New Posts New Posts RSS Feed: Tech Tip: Dynamic Entity Types
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Tech Tip: Dynamic Entity Types

 Post Reply Post Reply
Author
IdeaBlade View Drop Down
Moderator Group
Moderator Group
Avatar

Joined: 30-May-2007
Location: United States
Posts: 353
Post Options Post Options   Quote IdeaBlade Quote  Post ReplyReply Direct Link To This Post Topic: Tech Tip: Dynamic Entity Types
    Posted: 06-Jun-2007 at 12:49pm

Level 300
DevForce Enterprise

Sept 28, 2006

DevForce developers define “static” business object types at design time by mapping class definitions to objects in data source schemas such as tables, views, and stored procedures in relational databases.

Sometimes we don’t know the structure of the class we’ll need until runtime. For example:

  • A particular search can fetch data from many rows of a very large table depending upon how the user structures the query. Poor performance is a huge risk. We want to retrieve the minimum number of columns necessary to present the result in a grid. We don’t know which columns until the user specifies the query.
  • We want to generate some aggregate statistics from a table (counts, averages, etc.). We compose a query to retrieve them although we don’t know what we’re after (the columns returned by the query) until runtime, perhaps because the user picks the statistics from a menu.
  • We may need to build a class around a table we discover in the runtime database – a table that didn’t exist in the design-time database. This can be a “user-defined table” that our customer has added to the database in order to extend and customize user information managed by our application.

In all cases we’d like to represent the data as entities in our business object model. But we can’t use any of the static entity types output by the Object Mapper because we don’t know the “schema” of those entities until runtime.

Enter the “Dynamic Entity Type.” As of release 3.2.1.1, DevForce developers can create a new “dynamic” type – a new class – at runtime.

Dynamic entity type instances can be queried, created, modified, and deleted. They reside in the entity cache of a PersistenceManager’s and inherit from the DevForce Entity class, just like instances of the static entity types. A dynamic entity type may even be shared with other clients if the clients are n-tier deployed and use the same name for the type.

Keyed and Unkeyed Dynamic Entity Types

Dynamic entity types come in two basic flavors: those defined with, and those defined without a primary key.

Dynamic entity types with a primary key operate almost exactly like a statically defined DevForce entity type. Query results are merged into a
PersistenceManager according to the query’s MergeStrategy. The primary key helps the merge discover if the arriving entity is new to the cache or is already present; if present, the strategy determines whether the arriving entity updates the cached entity, replaces it, or is ignored.

Merge logic depends upon schema consistency across queries. It follows that the structure of the result of all queries for a keyed dynamic entity type must match the schema for that type. The type’s schema is only “open” for the first query.

On the other hand, when we query for dynamic entity types without a primary key, the PersistenceManager does not merge the results. Absent a primary key, it cannot determine if the arriving entity is already in the cache. Therefore, for keyless dynamic entities, the PersistenceManager first discards all prior instances of the type and then fills the cache with the query results. And in this circumstance, schema consistency is not an issue, so the PersistenceManager, upon detecting a difference, simply drops the old schema and adopts the new schema implied in the query result.

Creating Dynamic Entity Types

Dynamic entity types can be created, with or without a primary key, using the CreateType() method of the new DynamicEntityTypeBuilder class. Here, for example, is the code to create a dynamic entity type with a primary key, defined by name.

 

  C#:

 

Type type1 =

  DynamicEntityTypeBuilder.CreateType("foo1", "IdeaBladeTest1", “LastName”);

 

  VB.NET:

 

Dim type1 As Type = DynamicEntityTypeBuilder.CreateType( _

  "foo1", "IdeaBladeTest1", “LastName”)

 

In the above example, the first argument is the name for the type; the second argument is a DevForce DataSourceKeyName; the final argument is the name of the primary key column.

You can create a multi-part key simply by specifying the additional column names in subsequent parameters (no limit):

 

  C#:

Type type1 =

  DynamicEntityTypeBuilder.CreateType("foo1", "IdeaBladeTest1", “CompanyName”, “EmployeeNumber”);

                                 

  VB.NET:

Dim type1 As Type = DynamicEntityTypeBuilder.CreateType( _

  "foo1", "IdeaBladeTest1", “CompanyName”, “EmployeeNumber”)

Key columns can also be referenced by their column index. The equivalent of the multi-part key specification just illustrated would be the following, assuming that the column indexes for CompanyName and EmployeeNumber are 0 and 1, respectively. That data should come from the default datasource.

 

  C#:

 

Type aDynamicType =

  DynamicEntityTypeBuilder.CreateType("foo1", "Default", 0, 1);

 

  VB.NET:

 

Dim aDynamicType As Type = DynamicEntityTypeBuilder.CreateType( _

  "foo1", "Default", 0, 1)

 

To create a dynamic entity type without a primary key, simply omit the primary key column:

 

  C#:

 

Type type1 = DynamicEntityTypeBuilder.CreateType("foo1", "IdeaBladeTest1");

 

  VB.NET:

 

Dim type1 As Type = DynamicEntityTypeBuilder.CreateType( _

  "foo1", "IdeaBladeTest1")

An additional option for creating dynamic entity types will be available in the next release of DevForce, scheduled for early November: declaring the schema programmatically at runtime. That will permit the creation of an entity that has no database table behind it at all. Instances of such an entity can then be created and populated programmatically. And note that any instance of a dynamic entity, whether backed by a database table or not, can be persisted to a local file using the PersistenceManager’s familiar SaveEntitySet() method.


Querying for Instances of Dynamic Entity Types

Dynamic entity types can be queried either from the PersistenceServer via a PassthruRdbQuery or from the local PersistenceManager via a normal EntityQuery. (A forthcoming version of this feature will support querying for dynamic type entities from the PersistenceServer via either the StoredProcRdbQuery or the WsQuery.)

Querying from the
PersistenceServer (Backend Database)

  C#:

 

PersistenceManager pm = PersistenceManager.DefaultManager;

 

Type type1 =

  DynamicEntityTypeBuilder.CreateType("foo1", "Default", ”LastName”);

 

IEntityQuery query1 = new PassthruRdbQuery(

  type1, "select FirstName, LastName from Employee");

 

IList entities1 = pm.GetEntities(query1);

 

Type type2 = DynamicEntityTypeBuilder.CreateType("foo2", "Default");

 

IEntityQuery query2 =

  new PassthruRdbQuery(type2, "select count(*) from orders");

 

IList entities2 = pm.GetEntities(query2);

                                 

 

  VB.NET:

 

Dim pm As PersistenceManager = PersistenceManager.DefaultManager

Dim type1 As Type = DynamicEntityTypeBuilder.CreateType( _

  "foo1", " Default",”LastName”)

Dim query1 As IEntityQuery = New PassthruRdbQuery( _

  type1, "select FirstName, LastName from Employee")

Dim entities1 As IList(Of DynamicEntity) = _

  pm.GetEntities(Of DynamicEntity)(query1)

Dim type2 As Type = DynamicEntityTypeBuilder.CreateType("foo2", "Default")

Dim query2 As IEntityQuery = _

  New PassthruRdbQuery(type2, "select count(*) from orders")

Dim entities2 As IList(Of DynamicEntity) = _

  pm.GetEntities(Of DynamicEntity)(query2)

Querying from the PersistenceManager Cache

 

  C#:

 

PersistenceManager pm = PersistenceManager.DefaultManager;

 

Type type1 =

  DynamicEntityTypeBuilder.CreateType("foo1", "Default", ”LastName”);

 

// EntityQueries against dynamic entities automatically have

// EnableUDFQueries=true

EntityQuery query = new EntityQuery(type1, "LastName", EntityQueryOp.LT, "G");

 

IList entities =

  pm.GetEntities(query, QueryStrategy.CacheOnly);

                                 

  VB.NET:

 

Dim pm As PersistenceManager = PersistenceManager.DefaultManager

Dim type1 As Type = DynamicEntityTypeBuilder.CreateType( _

  "foo1", " Default",”LastName”)

' EntityQueries against dynamic entities automatically have

' EnableUDFQueries=true

Dim query As EntityQuery = _

  New EntityQuery(type1, "LastName", EntityQueryOp.LT, "G")

Dim entities As IList(Of DynamicEntity) = _

  pm.GetEntities(Of Entity)(query, QueryStrategy.CacheOnly)

Accessing Data in a Dynamic Entity Type Object

You can access the data in a dynamic entity type object by name, or by index, with the Entity indexing method.

 

  C#:

 

String lastName;

lastName = (String) aDynamicEntity[“LastName”]; // or

lastName = (String) aDynamicEntity[1];

                                 

  VB.NET:

 

Dim lastName As String

lastName = CType(aDynamicEntity(“LastName”), String) ' or

lastName = CType(aDynamicEntity(1), String)

This is the same approach we use to access data in a User-Defined Field (UDF).

Saving Changes

Currently new, modified, or deleted dynamic entities in the PersistenceManager cannot be saved back to the backend datastore. This will be supported in the next release of DevForce. Meanwhile, enjoy the local-persistence-only variety!

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down