Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Create data-driven applications with the Hera Application Framework

21 Dec 2006 1  
A brief overview of how the Hera Application Framework aids you in the development of data-driven applications.

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.

This is a showcase review for our sponsors at CodeProject. These reviews are intended to provide you with information on products and services that we consider useful and of value to developers.

Hera Application Framework

Introduction

The Hera Application Framework is a powerful object persistence framework designed to aid you in the development of data-driven applications. It relieves you from the time-consuming task of having to program the data transformation process between your data source and your object oriented business model. This functionality is being added automatically to your .NET classes at-runtime, based on the data source and the mapping which defines how the two relate to one another. By doing this at-runtime, the framework can determine the most optimal way of implementing this functionality, and therefore guarantee a higher performance. It also enables you to use a different data source, or change the mapping without the need to recompile your code.

Main features

  • Data source independent
  • Object Query Language
  • Automatic state management
  • Lazy loading
  • Transaction management
  • Concurrency handling
  • Strong-typed queries
  • Stored procedure mapping
  • User types
  • Caching

Choosing a data source

By using the Hera Application Framework, you are free to choose from a variety of possible data sources. The framework comes with two fully supported data handlers for relational databases, being Microsoft SQL Server and Oracle. These data handlers are referred to in the framework as gateways. You will typically have a mapping for each gateway you use in your project. This allows you to define database specific features in the mapping instead of your code, making your code more independent from the data source. One example of this is the use of identity columns in Microsoft SQL Server versus the use of sequences in an Oracle database.

In contrast to most object-relational frameworks on the market, the Hera Application Framework does not limit you to using only a relational database as a data source. The framework has been designed in such a way that we are able to implement a completely different kind of gateway which allows you to map your business model onto XML. This allows you to work with XML data in exactly the same way as you would with data coming from your relational database, making your code much more consistent. This also enables us to add a rather unique feature to the framework, as you will see later in this article.

Getting started

There are two possible ways to create a mapping between your business model and a data source. You can either write the mapping file manually, or you can use our Configurator utility which comes with the default application framework installation. The Configurator uses a database of your choice to hold the project�s settings. You need to define where these settings will be located; more information on this can be found in the documentation.

Let�s look at an example of how you would create an object oriented business model with the Configurator using Microsoft SQL Server as data source. In this example, we assume you have a table called Departments with the following structure:

CREATE TABLE Departments
(
    DepartmentID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Name VARCHAR(255) NOT NULL UNIQUE
)

After going through the Getting Started section in the documentation for setting up the Configurator, you can begin creating a new project.

Choose a project to work with

The Configurator will query your database for all possible tables that can be mapped onto .NET classes. Clicking the Add Class button presents you with a wizard, taking you through the necessary steps.

Select a table to convert to class

After selecting a table, the Configurator presents you with a list of all the columns, and suggests a property name and type for representing them in your .NET class. You can change the names of these properties and their type, if you want.

Choose columns to be mapped to members

The next step in the wizard will let you change the name, assembly, or namespace for your class. You can also choose a base class for the generated class. This can be a generic object you created to further enhance the functionality of your business objects.

Set properties for the class

Now that the Configurator knows about your first class, you can generate the code and start developing an application. Go to Tools -> Generate All Code, to do this. The generated folder will look like this:

Generated files and folders

You will now have the basic folders for a project, a sample App.config (which can easily be used as a web.config), two files for the generated Department class, the mapping file, and a C# project.

Sample project with Department class

The Configurator created two files for Department because of the way this project is being generated. You should never change code inside the DepartmentGenerated.cs file because this file will be overwritten in case you regenerate. Keep in mind that this is not a limitation; this is a design choice we made when generating code with the Configurator, and you are in no way bound to it if you should choose to create the mapping file manually.

Now that we have a basic project, we can start by using it to query data from our SQL Server database.

Querying data

Whereas you would normally write SQL to query your data, you can now take advantage of the Hera Application Framework�s built-in query language. However, before you can start querying, you need to create a Session. A Session is basically the scope in which you communicate with the data source.

using (Session session = Session.CreateSession())
{
    Query query = session.CreateQuery(�from Department�);
    DataList<Department> departments = query.List<Department>();
}

The session created here will use the default gateway, specified in the App.config file, to communicate with the data source. You can also specify another gateway. This allows you to work with several data sources at the same time. Using this session, we can create a query by issuing an Object Query Language (OQL) expression. In this case, we query all the department records from the database. Calling the generic List method on this Query object will transform the OQL expression to SQL and execute it against the database.

Relational data

Of course, not all data is as simple as this. In fact, it�s rather rare to find a table in the database which doesn�t have some kind of relationship with another. The Hera Application Framework offers full support for one-to-one, one-to-many, many-to-one, and many-to-many relations, including cascading operations.

Suppose you have another table called Employees defined as follows:

CREATE TABLE Employees
(
    EmployeeID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    FirstName VARCHAR(255) NOT NULL,
    LastName VARCHAR(255) NOT NULL,
    DepartmentID INT NOT NULL REFERENCES Departments
)

When returning to the Configurator for creating a new .NET class based on this table, the wizard will present you with an additional step.

Add new relations with existing classes

Clicking the Find All button here will automatically discover all relations that in some way refer to this table.

Find all relations

The Configurator detected a many-to-one relation between employees and their departments. You can always add or edit relations later on. In this case, you could edit the relations for the Department class to add a one-to-many relation to Employees. When regenerating the code, you will have a property on Employee of type Department.

Employee emp = session.Load<Employee>(10);
Console.WriteLine(emp.Department.Name);

The example above will query an Employee from the database passing its primary key. Next, we access the Employee�s Department property and write its name on the screen. As you can see, we didn�t have to write any code to query this Department since this is automatically done by the framework the moment you access the property, providing the session is still alive. This is called lazy loading, and ensures you only query what you actually use.

Using OQL with relational data is pretty straightforward as the following example shows:

// Query all departments having more than 5 employees

string query = "from Department d where d.Employees.Count > 5";

You can even set parameters to a value of another mapped type. The framework will then automatically determine how the relation between them is defined, and will add the correct criteria to the SQL expression.

Department dept = session.Load<Department>(1);

Query query = session.CreateQuery("from Employees" + 
              " e where e.Department = {Department}");
query.SetParameter("Department", dept);
DataList<Employee> employees = query.List<Employee>();

The framework can also take care of inverse relations for you. You can define in the mapping whether you want this behavior or not.

Department dept = session.Load<Department>(1);
Employee emp = session.CreateInstance<Employee>();
emp.Department = dept;

// dept.Employees automatically contains the new Employee

Assert.IsTrue(dept.Employees.Contains(emp));

Returning values

Whenever an object�s property value is determined by the data source, for example, when using an identifier or sequence, that value is automatically returned and the property that corresponds to this column is automatically updated.

Employee emp = session.CreateInstance<Employee>();
emp.Name = "Garfield";

session.Save(emp);
Assert.NotNull(emp.Id);

You can also define other properties as being returning-value properties, for example, when a table contains a last-modified column which is automatically set by database triggers.

User types

The Hera Application Framework also supports user types for grouping columns together. Mapping a property in a user type is as easy as mapping a property on the object itself.

Employee emp = session.Load<Employee>(10);

Console.WriteLine(emp.Audit.CreationDate);
Console.WriteLine(emp.Audit.CreatedBy);
Console.WriteLine(emp.Audit.LastModifiedDate);
Console.WriteLine(emp.Audit.LastModifiedBy);

Strong-typed queries

A common problem in applications using SQL to communicate to the database is the lack of type checks when setting parameters. In the Hera Application Framework, we solved this problem by adding support for strong-typed queries. By defining a strong-typed query class and using it throughout your application, you are sure that the parameter values in your query expression are always of the correct type. This further eliminates run-time errors which would otherwise occur when you would supply an incorrect value type. You can even add parameter validation logic to these properties so that wrong values can be detected at client side instead of having the database notify you with an error. These classes have to derive from the NamedQueryBase class in the framework, and should be defined in the mapping.

Creating named queries can also be easily done with the Configurator as shown in this screen. The query you enter can either be a native SQL query or an OQL expression.

Creating a strong-typed query

After generating the code, you have a new class in your project called DepartmentByName. Using the following code, you can query a department from the database giving a name as parameter.

DepartmentByName deptQuery = 
session.CreateNamedQuery<DepartmentByName>();
    
// Entering a wrong value type for name

// here will result in a compile-time error.

deptQuery.Name = "Sales";

Department dept = query.Load<Department>();

Microsoft Exchange SDK

As said at the beginning of this article, by implementing an XML gateway, we are able to create a rather unique feature. Bundled with the Hera Application Framework is an SDK for working with Microsoft Exchange 2000/2003/2007. This SDK is completely built on the framework itself. Communication to an Exchange server is established via WebDAV. By mapping the XML communication to the server on a user friendly business model, it is now easier than before to integrate Exchange in your applications.

using (ExchangeServer server = new ExchangeServer())
{
    server.Location = "MyExchangeServer";
    server.Credential = new NetworkCredential("UserName", "Password");

    // Create a note

    Note note = server.CreateNote();
    note.Subject = "My Own Note";
    note.TextDescription = "This is a test note.";
    if(File.Exists(@"c:\logs.txt"))
    {
        note.AddAttachment(@"c:\logs.txt");
    }
    server.Save(note);
  
    // Create an appointment

    Appointment appointment = server.CreateAppointment();
    appointment.Subject = "My Appointment";
    appointment.HtmlDescription =  
      "<font color=red>Test</font> <i>appointment</i>.";
    appointment.StartTime = DateTime.Now.AddHours(2);
    appointment.EndTime = DateTime.Now.AddHours(4);
    server.Save(appointment);

    // List all contacts

    foreach(Contact contact in server.Contacts)
    {
        Console.WriteLine(contact.Name);
    }
}

License

The Hera Application Framework is licensed as being free for non-commercial use. Once you start building programs based on our framework with the prospect of deploying it in a production environment, you will have to purchase a service contract. Signing up for a service contract allows you to post tickets in our service desk application, and gives you access to our secure forum. For more information, visit our website.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here