Getting the Job Done with XAF - Part 1
Introduction
What if it was really easy to develop a reasonable complex application, something along the lines of creating just a few classes and be done with it? This comes at a price, but then we all know that there is no such thing as a free lunch.
The good news is that the solution only contains 63 lines of code. Actually that's what I really want to tell you about, getting the job done with a minimal amount of work.
We are just going to create a number of Domain Object classes, no Windows Forms or ASP.Net coding, and still end up with functioning Windows Forms and ASP.Net applications.

XAF from DevExpress is a framework that allows us to create a wide range of applications with a minimum of development effort. Out of the box it provides a lot of functionality commonly required during development of line of business (LOB) applications. XAF leverages DevExpress components for .Net, and XPO – their object relational mapping (ORM) solution.

Requirements
You get XAF with DXperience Universal Subscription, . There is also a free trial of the product.
Creating the solution
A new XAF based solution is created in the usual way, using the Visual Studio New Project Dialog.

By choosing the Applications Solution we get a solution containing both a Windows Forms and a Web application. I think that’s a neat thing, and the initial solution looks like this:

At this point we have to open the app.config for the Windows Forms project XAFSmartBooking.Win and the Web.Config for the Web Application project XAFSmartBooking.Web. Uncomment the connection strings we want, then save and build the solution.
We now have a Windows Forms Application:

and a Web Application

It’s nice that user management is built in from the start, without a single line of code.
Creating Domain Objects
Since we are working on a booking application, we need something to book, a bookable object, if you want. Right click on the XAFSmartBooking.Module project and select Add -> New Item.

We create a new Domain Object called Bookable, this will be our abstract base class for bookable objects. Initially I’d like to be able to book buildings, rooms and vehicles. So we just add the required types using the same procedure giving us a simple hierarchy structure.

The Code
Bookable
is our base domain object entity, and it's derived from BaseObject
the predefined class that all XAF domain objects descends from. We define one string property “Name”, and give it a [Size(255)] attribute definition. The Size attribute is used to declare the size of the field in the underlying data storage.
public abstract class Bookable : BaseObject
{
private string name;
public Bookable(Session session)
: base(session)
{ }
public override void AfterConstruction()
{
base.AfterConstruction();
}
[Size(255)]
public string Name
{
get
{
return name;
}
set
{
SetPropertyValue("Name", ref name, value);
}
}
}
Facility
is the common base class for Building
and Room
. It also exposes a property of type PhoneNumber
, one of many predefined classes from the XAF Business Class Library.
During construction we create a new instance of the PhoneNumber
class if our domain object is not in the loading state. A domain object is in a loading state if the entity already exists in the data storage, and the constructor is called during a load operation.
To facilitate saving of the phonenumber, as part of a save operation for a Facility
object, we override the OnSave
method, and save the phone number.
The [ExpandObjectMembers(ExpandObjectMembers.InDetailView)] attribute declaration forces expansion of the properties defined on the PhoneNumber
for detail views of Facility
objects.
public abstract class Facility : Bookable { private PhoneNumber phoneNumber; public Facility(Session session) : base(session) { if (!IsLoading) { phoneNumber = new PhoneNumber(session); } } public override void AfterConstruction() { base.AfterConstruction(); } protected override void OnSaving() { phoneNumber.Save(); base.OnSaving(); } [ExpandObjectMembers(ExpandObjectMembers.InDetailView)] public PhoneNumber PhoneNumber { get { return phoneNumber; } set { SetPropertyValue("PhoneNumber", ref phoneNumber, value); } } }
TypeBase
will be used as a base class for classes used to descriminate between various types of buildings, room, and vehicles.
The [NonPersistent] attribute ensures that XAF, or rather XPO, does not create a table for this type. The Name property will be stored in the same table as the properties of direct descendants. [Indexed(Unique=true)] instructs XAF to create a unique index on the column used to store the property. The column will be unique for the descendant type, and not for instances of the TypeBase
class.
[NonPersistent] public abstract class TypeBase : BaseObject { private string name; public TypeBase(Session session) : base(session) { } public override void AfterConstruction() { base.AfterConstruction(); } [Size(255)] [Indexed(Unique=true)] public string Name { get { return name; } set { SetPropertyValue("Name", ref name, value); } } }
BuildingType
is one of the three classes used to define discriminators for our Bookable descendants, the other to being RoomType
and VehicleType
.
[Association("Building-BuildingType", typeof(Building))] defines the one side of a one-to-many relationship between BuildingType
and Building
. The Buildings
property returns the associated Building
objects as a collection.
[DefaultClassOptions] [NavigationItem("Facilities")] [ImageName("BO_Category")] public class BuildingType : TypeBase { public BuildingType(Session session) : base(session) {} public override void AfterConstruction() { base.AfterConstruction(); } [Association("Building-BuildingType", typeof(Building))] public XPCollectionHere is ourBuildings { get { return GetCollection ("Buildings"); } } }
Building
class. It includes the many side of the on-to-many association with the BuildingType
class, and it also uses another predefined class, Address
from the XAF Business Class Library.
[DefaultClassOptions] [NavigationItem("Facilities")] [ImageName("BO_Organization")] public class Building : Facility { private BuildingType type; private Address address; public Building(Session session) : base(session) { if (!IsLoading) { address = new Address(session); } } public override void AfterConstruction() { base.AfterConstruction(); } protected override void OnSaving() { address.Save(); base.OnSaving(); } [Association("Building-BuildingType", typeof(BuildingType))] public BuildingType Type { get { return type; } set { SetPropertyValue("Type", ref type, value); } } [ExpandObjectMembers(ExpandObjectMembers.InDetailView)] public Address Address { get { return address; } set { SetPropertyValue("Address", ref address, value); } } }
Concluding remarks
It doesn’t get much easier than this. With just 63 lines of coding we have created a solution that maintains its own data storage. XAF supports popular database management systems like Microsoft SQL Server, IBM DB2, Oracle RDBMS, and many more.
As an added bonus we have both a Windows Forms Application and an ASP.Net Application.
The next part of the series will add support for booking, and it’s going to look nice too.
History
12th of January 2011 - Initial posting
发表评论
N6O4k2 Red your blog post and loved it. Have you at any time imagined about visitor putting up on other relevant weblogs equivalent to your blog?
lAylkp I reckon something really interesting about your web blog so I saved to my bookmarks.
IGI9qf I value the article.Really thank you! Cool.
MSHD6D wow, awesome blog.Really looking forward to read more. Keep writing.
to seeke out the situation of Athens, which when he found Socrates having something like a loose robe thrown partly over her. From the 5:21. For as the Father raiseth up the dead and giveth life: so the Son