Jun 30, 2005 / Atlas Project: AJAX in ASP.NET 2.0

0 comments

Very promising project for creating AJAX based applications on ASP.NET 2.0. It seems it will be released next year, and features set looks good. Atlas Project will include new controls with AJAX support, like auto-complete textboxes, drag and drop, client side paging and sorting in DataView and so on; object-oriented script framework; web services integration.

With this feature ASP.NET may greatly improve UI and this will be very good reason for developers to migrate to ASP.NET. We'll see.

Jun 23, 2005 / Wicket - One more Java Web Component Framework

1 comments

Wicket is one more component framework like Tapestry, JSF or ASP.NET. However, it's light and very simple. Well, ASP.NET is simpler :)

One example (displays textarea with submit button and messages list):

public GuestBook()
{
 add(new CommentForm("commentForm"));
 add(commentListView = new ListView("comments", commentList)
 {
     public void populateItem(final ListItem listItem)
     {
         final Comment comment = (Comment)listItem.getModelObject();
         listItem.add(new Label("date", comment.getDate()));
         listItem.add(new MultiLineLabel("text", comment.getText()));
     }
 });
}

Jun 21, 2005 / NHibernate vs. NEO: Face to Face. Part I

1 comments

There are many open source O/R mapping frameworks have been appearing for .NET platform during the last year. Most of them are ugly and just few of them ready for real-world development. Among open source solutions, NEO and NHibernate stay on the top of other in O/R mapping world. That is why we will compare them in this series of articles. Face to face.

In this article we will introduce NEO framework. I have very good experience with NEO, since we use it in TargetProcess project - ASP.NET based agile project management system. The project is quite mature and this will be the real experience from real production project.

Short Intro

NEO

NEO is a framework originally created for .NET. It is quite simple and quite featured to solve almost all usual O/R mapping problems. http://neo.codehaus.org

NHibernate

NHibernate is a .NET port of very popular Java based Hibernate framework. There is a very clear trend last years to port all good tools from Java world to .NET. Hibernate is widely used and has been evolved into one of the most powerful O/R mapping solutions. http://nhibernate.sourceforge.net/

NEO Framework

Usage of almost any O/R mapping tool is quite uniform with some deviations. There are six steps to start using NEO:

  1. Create domain model (UML diagram, text description or your mind)
  2. Create domain descriptor in XML format for NEO
  3. Generate C# classes and SQL queries for domain model
  4. Include C# classes into project
  5. Create the database and execute SQL queries
  6. Use NEO framework to handle persistence objects

Creating mappings

Any O/R mapping tool works with domain model. Some of them closer to database, while some of them closer to domain model. NEO is on the middle ground. You may create a database and generate domain model descriptor file, or you may create domain model descriptor and then generate database. I prefer the second way.

Let's take very simple domain mode. This is a kid of very basic Bug tracking system. You may add a project, add bugs, assign them on users and add comments to the bugs. Here is the class diagram.

Now we should translate this fancy UML picture to NEO language - model descriptor in XML format. We are starting with project class mapping. As you maybe know, each class in domain model has a table in a database (we'll not consider inheritance for now). So, all objects of Project class will be stored in a table projects.

<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
<!DOCTYPE database SYSTEM "Resources/norque.dtd">
<database name="tp" package="Neo.Web.Model"
defaultIdMethod="native" defaultJavaNamingMethod="underscore">

<table name="projects" javaName="Project">
. . .
</table>

</database>

Well, maybe you are slightly confusing with javaName property in C# based framework. But a rational description exists as you may guess. The fact is that NEO uses DTD of Torque O/R mapping tool that was writing on Java and for Java.

We have mapped the class, and now should do the same for class properties. Our Project class has four properties: Name, Description, StartDate and ProjectId. In database, ProjectId will be an autoincremental Primary Key column. Mappings for all the other properties are very simple.

<table name="projects" javaName="Project">
<column name="project_id" primaryKey="true" autoIncrement="true"
required="true" type="INTEGER" />
<column name="name" required="true" type="VARCHAR" size="150" />
<column name="description" required="false" type="VARCHAR" size="600" />
<column name="start_date" required="true" type="DATE" />
</table>

Let's skip mapping of User class, since it is almost the same, and look right into Bug class. According to Domain Model, each project could have a collection of Bugs. This is one-to-many relation and in a Relational Databases realm represented by a simple Foreign Key.

<table name="bugs" javaName="Bug">
<column name="bug_id" primaryKey="true" autoIncrement="true" required="true"
type="INTEGER" />
<column name="name" required="true" type="VARCHAR" size="250" />
<column name="description" required="false" type="VARCHAR" size="2500" />
<column name="effort" required="false" type="DECIMAL" />
<column name="status" required="true" type="INTEGER" />
<column name="project_id" required="true" type="INTEGER" />
<foreign-key foreignTable="projects" name="Project" onDelete="cascade">
<reference local="project_id" foreign="project_id" />
</foreign-key>
</table>

All Bug objects will be stored in bugs table, bug_id will be a primary key and project_id will be a foreign key on projects table.

<foreign-key foreignTable="projects" name="Project" onDelete="cascade">
Name attribute sets the name of relation. In this case each Bug object will have a reference at Project object and in code you will be able to write something like this:
String projectName = bug.Project.Name;
<reference local="project_id" foreign="project_id" />

Reference sets columns for foreign key. In this case project_id column should exist in bugs table and in projects table.

If we want to have collections of bugs in a project object, we should add information about bugs into project class definition:

<table name="projects" javaName="Project">
. . .
    <iforeign-key foreignTable="bugs" name="Bugs" onDelete="cascade">
<ireference local="project_id" foreign="project_id" />
</iforeign-key>
</table>
public ICollection GetBugs()
{
return new BugList(this.Bugs);
}

Finally, the full mapping will look like that:

<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
<!DOCTYPE database SYSTEM "Resources/norque.dtd">
<database name="tp" package="Neo.Web.Model" defaultIdMethod="native"
defaultJavaNamingMethod="underscore">

<table name="projects" javaName="Project">
<column name="project_id" primaryKey="true" autoIncrement="true"
required="true" type="INTEGER" />
<column name="name" required="true" type="VARCHAR" size="150" />
<column name="description" required="false" type="VARCHAR" size="600" />
<column name="start_date" required="true" type="DATE" />
<iforeign-key foreignTable="bugs" name="Bugs" onDelete="cascade">
    <ireference local="project_id" foreign="project_id" />
</iforeign-key>
</table>

<table name="users" javaName="User">
<column name="user_id" primaryKey="true" autoIncrement="true"
required="true" type="INTEGER" />
<column name="name" required="true" type="VARCHAR" size="150" />
<column name="login" required="true" type="VARCHAR" size="50" />
<column name="password" required="true" type="VARCHAR" size="50" />
</table>

<table name="bugs" javaName="Bug">
<column name="bug_id" primaryKey="true" autoIncrement="true"
required="true" type="INTEGER" />
<column name="name" required="true" type="VARCHAR" size="250" />
<column name="description" required="false" type="VARCHAR" size="2500" />
<column name="effort" required="false" type="DECIMAL" />
<column name="status" required="true" type="INTEGER" />
<column name="project_id" required="true" type="INTEGER" />
<column name="user_id" required="true" type="INTEGER" />
<foreign-key foreignTable="projects" name="Project" onDelete="cascade">
    <reference local="project_id" foreign="project_id" />
</foreign-key>
<foreign-key foreignTable="users" name="Owner">
    <reference local="user_id" foreign="user_id" />
</foreign-key>
<iforeign-key foreignTable="comments" name="Comments" onDelete="cascade">
    <ireference local="bug_id" foreign="bug_id" />
</iforeign-key>
</table>

<table name="comments" javaName="Comment">
<column name="comment_id" primaryKey="true" autoIncrement="true"
required="true" type="INTEGER" />
<column name="text" required="false" type="VARCHAR" size="1000" />
<column name="date" required="true" type="DATE" />
<column name="user_id" required="true" type="INTEGER" />
<column name="bug_id" required="true" type="INTEGER" />
<foreign-key foreignTable="users" name="User">
    <reference local="user_id" foreign="user_id" />
</foreign-key>
<foreign-key foreignTable="bugs" name="Bug" onDelete="cascade">
    <reference local="bug_id" foreign="bug_id" />
</foreign-key>
</table>
</database>

Generating Model Classes

Now we have all four classes mapped and ready to generate SQL and ะก# code for them. NEO has a code generation tool neo.exe that could be found in [neo root folder]\src\Tools\CmdLineTool folder. It is convenient to create bat file with all required commands.

neo.exe -r Resources -f -sql true -sqldrop true -o Sql model.xml neo.exe -r Resources -user true model.xml neo.exe -r Resources -support true -o Base model.xml

First command generates SQL queries and puts them into Sql folder. Using these queries you may create database for sample application. Second command generates model classes that may be modified by user (will not be regenerated by NEO in future). Third command creates base model classes that will be regenerated by NEO when model changed. Finally, we will have the structure shown on the picture below:

After bat file execution, we should just include new classes into our project and change namespaces.

Now we should create a database and execute generated model.sql script from Sql folder.

Connecting to Database

Let's do the last part of preparations - connect to database. First of all, create DataStoreFactory class that will create database connections. There will be two parameters in Web.config

<add key="ConnectionString" value="data source=(local);initial catalog=ormapping;uid=sa;pwd=" />
<add key="DatabaseServer" value="Neo.SqlClient.SqlDataStore,Neo" />

DataStoreFactory has just one Create method:

public IDataStore Create()
{

 string className =
  ConfigurationSettings.AppSettings["DatabaseServer"];

 string conn =
  ConfigurationSettings.AppSettings["ConnectionString"];

 return (IDataStore)Activator.CreateInstance(
  Type.GetType(className + ",Neo"),new object[] {conn});

}

It's time to have fun with NEO framework. The first application's page will add new project and shows projects list. Oh, we did not finish connection operations. Ok, that's easy. Just instantiate IDataStore and create an instance of ObjectContext. Actually, ObjecyContext is very interesting beats and it is a Unit of Work pattern. It stores all changes of loaded objects and mandatory for all operations with NEO.

// create data store
DataStoreFactory store = new DataStoreFactory();
IDataStore dataStore = store.Create();

// create context for changes tracking
context = new ObjectContext(dataStore);

Persistence

There is a web form on the page, as usual, with several text boxes and a button. When user fills out the form and pushes the button, new project should be added into the database. The following event handler will do all actions:

private void btnAddProject_Click(object sender, System.EventArgs e)
{
// create new project
ProjectFactory projectFactory = new ProjectFactory(context);
Project project = projectFactory.CreateObject();

// set project properties
project.Name = txtName.Text;
project.Description = txtDescription.Text;
project.StartDate = Convert.ToDateTime(txtStartDate.Text);

// save new project into the database
context.SaveChanges();
}

First, we instantiate ProjectFactory. This class responsible for all operations with projects: create, retrieve, delete and so on. Then we create a new project. Note that this new project is not in the database right now. On the next step we set all project properties from form's fields. And, finally, we save all changes in ObjectContext into the database. In our case, NEO will generate INSERT query.

Now it is required to get all projects from database and show them in a list. Code in Page_Load handler will be very simple:

private void Page_Load(object sender, System.EventArgs e)
{
// create data store
DataStoreFactory store = new DataStoreFactory();
IDataStore dataStore = store.Create();

// create context for changes tracking
context = new ObjectContext(dataStore);

// retrieve all projects from database
ProjectList projects = new ProjectFactory(context).FindAllObjects();

// fill datagrid
lstProjects.DataSource = projects;
lstProjects.DataBind();
}

Again, we use ProjectFactory to retrieve all projects from database and use the list as a DataSource for lstProjects DataGrid. That's it.

Conclusion

Do you remember times when dynamic SQL or stored procedures had been used for database operations? NEO or any other good O/R mapping solution makes life easier and code lighter. A lot.

That was just quick start with NEO. In the next article we will check more complex topics, like complex queries, possible architectural solutions for ObjectContext handling, detached database and TDD with NEO, inheritance problem and so on.

Jun 16, 2005 / How To Start Extreme Programming

0 comments

Kent Beck describes three strategies to start practice Extreme Programming:

  • Toe Dipping: slowly, practice by practice
  • Racing Dives: with help of experienced coach
  • Cannonballs: all possible practice from the beginning of the project

Each strategy has its place. Read the article and define best strategy for you.

Jun 6, 2005 / JSF vs. ASP.NET v2.0

0 comments
As I've already mentioned, Java and .NET getting closer. Even Web RAD quite the same with JSF.
Subscribe to the RSS feed
Stay tuned by having the latest updates via RSS
Follow TargetProcess on Twitter
Get in touch with our team

TargetProcess is an agile project management tool. It is designed to solve distributed teams problems and support agile development processes.



Key Features

  • Full Agile Project Management Support (Scrum, XP, Custom)
  • Productivity Tools (Tp.Tray, ToDo list, dashboards, Inline editing)
  • Customizable Development Process
  • Subversion Integration
  • Integrated Bug Tracking, Help Desk, Time Tracking

Get TargetProcess for Free (5 users pack)

Previous Posts



    follow me on Twitter

    Archives