Chad Coon
October 2004
Applies to:
Microsoft Business Framework (MBF)
Entity persistence (EP)
Business Portal SDK
Microsoft Business Solutions
Summary: Review some of the goals of the entity persistence subsystem in the Microsoft Business Framework, and review some of the classes and methods developers can use in their Business Portal applications to handle entity persistence related tasks. (11 printed pages)
Contents
Introduction
MBF and the Business Portal SDK
Entity Persistence Overview
Virtual Collections
Sample Entities and Model
Virtual Collection Members
Conclusion
Introduction
Entity persistence (EP) is a term used to describe the process of persisting (saving), deleting, and changing object-oriented entities. The process involves a permanent storage mechanism, such as a relational database.
Writing code to persist object-oriented entities can be one of the most time-consuming tasks involved in developing a business application. The application can also end up tightly coupled to the data store and the data schema.
The Microsoft Business Framework (MBF) contains a layer of entity persistence functionality. Entity persistence in MBF decouples the application code from the data schema and simplifies the programming model for the application developer.
MBF and the Business Portal SDK
The Microsoft Business Framework (MBF) is a set of application development tools that are designed to make business application development easier and faster. MBF is a framework that can be used to build many types of applications and will be the development platform used to build future business applications from Microsoft Business Solutions.
The Business Portal SDK is a software development kit which is based upon MBF. The Business Portal SDK contains and exposes a portion of MBF functionality. This document will inform developers how they can use some of the Entity Persistence-related MBF components that ship with the Business Portal SDK.
Entity Persistence Overview
The Microsoft Business Framework contains a layer of entity persistence functionality that simplifies the process of persisting entities for application developers. Entity persistence is just one of many subsystems in MBF, but it is one of the most useful and important subsystems.
CRUD Operations
The process of persisting entities will involve CRUD operations. CRUD stands for create, read, update, and delete:
- Creating entities refers to the process of creating and persisting a new entity. This process will result in an INSERT statement if Microsoft SQL Server is the data store.
- Reading entities does not result in data manipulation. It only involves reading existing entity data. If SQL Server is the data store, then the read process is synonymous with a SELECT statement.
- Updating an entity means that an existing, persisted entity is read and changed, and the changes are persisted back to the data store. SQL Server requires an UPDATE statement to change an existing record.
- Deleting entities is the process of removing an entity that was previously persisted to the data store. The deletion of an entity will result in the execution of a DELETE statement on the SQL Server if SQL Server is the data store.
Entity Persistence API Overview
Entity persistence functionality is exposed through a number of methods. The code needed to perform certain EP functions has been encapsulated in methods that were either written by the MBF Code Generator or inherited from a base class.
The method names generated by the code generator are generally very descriptive of the function they perform. Every entity for which the Code Generator generates code will have a corresponding class with methods such as FindByID(), CreateByID(), Delete(), and Save(). These methods are stored in a separate, but related, .NET class called a virtual collection.
Benefits of Using MBF Entity Persistence
The entity persistence subsystem within MBF provides some significant advantages to the application developer. One of the most apparent benefits is that persistence tasks can be accomplished with much less code. For example, the task of saving a new entity may require several lines of code if the developer is only using Microsoft ADO.NET. The same task can be completed with only one line of code when using the MBF entity persistence layer.
Another feature of MBF entity persistence is that the developer deals with the object-oriented entities, and not the tables. Most application developers will appreciate a development environment that doesn't require them to deal with database tables. In fact, the developer doesn't necessarily need to know anything about the data schema during design time.
The third advantage to using MBF entity persistence is that, because the entity and the database have been decoupled by means of entity relational maps, the data schema can change without breaking application code. In this scenario, only the entity relational maps need to be changed. When the maps are changed to reflect the data changes, the application code will continue to work.
Virtual Collections
Virtual collections are the classes that contain the entity persistence functionality for their respective entities. Virtual collections also serve as "entity factories" in the sense that they are the classes used to instantiate new entities (the constructors in the entity classes are not accessible). Every entity has one entity virtual collection.
The Code Generator and Virtual Collections
After modeling an entity, an application developer will use this model and the MBF code generator to produce a code file. This code file contains the entity class. The code generator will also produce a second code file for each entity, and this file will store the virtual collection class.
Nothing is needed from the developer to produce this class; the code generator always produces the virtual collection code file at the same time it produces the entity code file.
After generating code, the developer will be able to see both code files in Solution Explorer.
.gif)
Figure 1. VirtualCollection code file.
EntityVirtualCollection
Examination of the virtual collection code file reveals that each entity virtual collection class inherits from Microsoft.BusinessFramework.Entity.EntityVirtualCollection. EntityVirtualCollection encapsulates a large portion of entity persistence functionality. When browsed in Object Browser, developers can inspect several entity persistence methods and their overloads.
A few methods aren't included in EntityVirtualCollection and are instead implemented in the entity's virtual collection class. These methods' signatures depend on the entity key. The key for each entity may differ in the number of properties involved and their type, so these methods cannot be implemented until this information regarding the entity is known.
Sample Entities and Model
A sample model has been created to demonstrate the entity persistence API. The model represents a very simplified pizza order tracking system. All model entities are persisted into the company database. Each entity has one table to hold its data.
The Model
This is the model that was created for the demonstration code:
.gif)
Figure 2. Entity persistence API sample model.
There are three entities that were created for the sample code: DeliveryDriver, PizzaOrder, and PizzaOrderLineItem. These entities reside in the EP.Demo namespace. The Customer entity that appears on the diagram is the same Customer entity that resides in the Microsoft.Dynamics.Receivables.Customer namespace.
The PizzaOrder and DeliveryDriver entities are root entities, while the PizzaOrderLineItem is a non-root entity.
Model Relationships
All relationships in the model are owned by the PizzaOrder entity. The PizzaOrder entity contains two directed associations and one composition association.
The first directed association is to the Great Plains Customer entity. The association results in a CustID property being added to the PizzaOrder entity and represents the customer who placed the order.
The second directed association is to the DeliveryDriver entity. The association results in a DriverID property being added to the PizzaOrder entity and represents the delivery driver who delivered the order.
Virtual Collection Members
This section will describe certain members of the virtual collection class that will be generated by the code generator tool. Some sample code will be given in certain instances. This code was created in the context of a console application, but it is applicable in many types of applications, including web services, ASP.NET, and Windows forms applications.
FindByID()
FindByID() is a method that retrieves a specific instance of an entity. The input parameter(s) type(s) will always match that of the entity's key. For example, if your entity contains three attributes in its key, then the FindByID() method will accept three input parameters.
FindByID() always retrieves one and only one entity instance.
Overloads
Since the FindByID() method requires the entire entity key to retrieve only one instance of the entity, there are no additional overloads of this method.
Code Sample
The following code retrieves a specific instance of a DeliveryDriver entity and displays the details of the driver. Since this is the first code sample, there is some code included that demonstrates how to initialize the framework and set the company.
// bootstrap the framework
EnterpriseSession.Initialize();
Console.WriteLine("EnterpriseSession initialized...");
// retrieve the Two Inc. company
CompanyVirtualCollection companyVC =
new CompanyVirtualCollection();
Company company = companyVC.FindByID(-1);
Console.WriteLine("company retrieved...");
// set the DefaultParentKey equal to the Two Inc. key
EnterpriseSession.DefaultParentKey = company.GetKey();
Console.WriteLine("ParentKey set...");
// instantiate DeliveryDriver virtual collection
DeliveryDriverVirtualCollection deliveryDriverVC =
new DeliveryDriverVirtualCollection();
Console.WriteLine("virtual collection instantiated...");
// retrieve DeliveryDriver
DeliveryDriver deliveryDriver = deliveryDriverVC.FindByID("CNELSON");
Console.WriteLine("driver retrieved from database...");
// display deliveryDriver properties
Console.Write("\nID: {0}\nName: {1}\nDate of Birth: {2}\n\n",
deliveryDriver.ID, deliveryDriver.Name, deliveryDriver.DateOfBirth);
// end application
Console.WriteLine("press enter to continue...");
Console.ReadLine();
This is the output:
.gif)
Figure 3. DeliveryDriver code output.
CreateByID()
When the developer needs to create a new instance of an entity and the values of the key fields are known, the CreateByID() method is used. Like FindByID(), the signature of CreateByID() will vary depending on the key fields in the entity.
CreateByID() will return an instance of the entity, but it still needs to be persisted back to the database (this will be covered later in the document).
Overloads
Since the entire entity key is required to execute this method, there are no additional overloads for the method.
Code Sample
The following code creates a new instance of the DeliveryDriver entity.
// instantiate DeliveryDriver virtual collection
DeliveryDriverVirtualCollection deliveryDriverVC =
new DeliveryDriverVirtualCollection();
// create DeliveryDriver
DeliveryDriver deliveryDriver =
deliveryDriverVC.CreateByID("JJOHNSON");
// set deliveryDriver properties
deliveryDriver.Name = "Joe Johnson";
deliveryDriver.DateOfBirth =
new Microsoft.Dynamics.Common.Date(1980, 12, 10);
Create()
The Create() method is similar to CreateByID(). When Create() is called, the key fields do not need to be passed to the method; they can be set later.
Overloads
The overload that takes no parameters and that appears in the following code sample is the only overload that will be addressed in this document.
Code Sample
The following code sample creates a new delivery driver and sets all properties after the entity is instantiated. Notice that the return value from the Create() method must be cast to a DeliveryDriver type because the return value is an IEntity.
// instantiate DeliveryDriver virtual collection
DeliveryDriverVirtualCollection deliveryDriverVC =
new DeliveryDriverVirtualCollection();
// create DeliveryDriver
DeliveryDriver deliveryDriver =
(DeliveryDriver)deliveryDriverVC.Create();
// set deliveryDriver properties
deliveryDriver.ID = "JJOHNSON";
deliveryDriver.Name = "Joe Johnson";
deliveryDriver.DateOfBirth =
new Microsoft.Dynamics.Common.Date(1980, 12, 10);
Save()
The Save() method is called after an entity has been instantiated and the properties on the entities have been set. When the entity is ready to be persisted to the database, the entire entity is passed to the Save() event.
Overloads
The only overload of this method accepts an IEntity as an input parameter.
Code Sample
The following code sample retrieves a pizza order from the database, changes the customer that the order is assigned to, and then saves the pizza order back to the database. Notice the setting of the virtual collection's FindOptions.ReadOnly property. This property is set to true by default, and an exception is thrown if the setting is left to true at the time Save() is called.
// instantiate Pizza Order virtual collection
PizzaOrderVirtualCollection pizzaOrderVC =
new PizzaOrderVirtualCollection();
pizzaOrderVC.FindOptions.ReadOnly = false;
// retrieve PizzaOrder
PizzaOrder pizzaOrder = pizzaOrderVC.FindByID(3);
// instantiate the new customer
CustomerVirtualCollection customerVC = new CustomerVirtualCollection();
customerVC.FindOptions.ReadOnly = false;
Customer customer = customerVC.FindByID("AARONFIT0001");
// set pizzaOrder properties
pizzaOrder.CustID = customer.GetKey();
// persist to database
pizzaOrderVC.Save(pizzaOrder);
Delete()
The Delete() method removes an instantiated entity from the database. The entity must already be retrieved from the database. After the entity has been retrieved, the entity instance is passed to the Delete() method to remove it from the database.
Overloads
There are two versions of this method. The first takes an IEntity as the input parameter. The instance of the entity qualifies because it inherits from IEntity. The second takes an instance of EntityKey.
Code Sample
The following code sample creates a new instance of DeliveryDriver and persists it to the database. After the instance is saved to the database, it is retrieved so it can be passed to the Delete() method.
// instantiate Delivery Driver virtual collection
DeliveryDriverVirtualCollection deliveryDriverVC =
new DeliveryDriverVirtualCollection();
deliveryDriverVC.FindOptions.ReadOnly = false;
// create the DeliveryDriver
DeliveryDriver deliveryDriver = deliveryDriverVC.CreateByID("JTEST");
// set deliveryDriver properties
deliveryDriver.Name = "Joe Test";
deliveryDriver.DateOfBirth =
new Microsoft.Dynamics.Common.Date(1984, 8, 8);
// persist to database
deliveryDriverVC.Save(deliveryDriver);
// retrieve the entity
deliveryDriver = deliveryDriverVC.FindByID("JTEST");
Console.Write("Entity persisted...");
Console.ReadLine();
// delete the recently saved entity
deliveryDriverVC.Delete(deliveryDriver);
DeleteByID()
The DeleteByID() method removes an entity from the database without instantiating the entity. If the key values are known at runtime, this method can be used to delete the entity very quickly. The signature of the method is dependant on the identity fields for that entity. There is always one input parameter for each field involved in the entity key.
Overloads
Since the entire entity key is required to execute this method, there are no additional overloads for this method.
Code Sample
The following code sample instantiates and saves a new instance of DeliveryDriver, then deletes it using the DeleteByID() method. After the entity is saved to the database, it is not retrieved before being saved, as this is unnecessary when using the DeleteByID() method.
// instantiate Delivery Driver virtual collection
DeliveryDriverVirtualCollection deliveryDriverVC =
new DeliveryDriverVirtualCollection();
deliveryDriverVC.FindOptions.ReadOnly = false;
// create the DeliveryDriver
DeliveryDriver deliveryDriver = deliveryDriverVC.CreateByID("JTEST");
// set deliveryDriver properties
deliveryDriver.Name = "Joe Test";
deliveryDriver.DateOfBirth =
new Microsoft.Dynamics.Common.Date(1984, 8, 8);
// persist to database
deliveryDriverVC.Save(deliveryDriver);
Console.Write("Entity persisted, press enter to continue...");
Console.ReadLine();
// delete the recently saved entity
deliveryDriverVC.DeleteByID("JTEST");
Conclusion
This whitepaper has reviewed some of the goals of the entity persistence subsystem and some of the challenges the Microsoft Business Framework hopes to address. It has also documented some of the classes and methods developers can use in their Business Portal applications to handle entity persistence related tasks.
Support for the Business Portal SDK is available for registered customers and partners by visiting the following URL or calling 888-477-7877:
https://mbs.microsoft.com/support/newstart.aspx