XAF – The State of Domain Components Technology in v2011 Vol 1

XAF Team Blog
02 June 2011

EDIT:
Domain Components (DC) is in maintenance mode and we do not recommend its use in new software projects.


We are happy to announce that in v2011 vol1 the Domain Components (DC) technology leaves CTP and reaches the Beta stage. During this release, XAF and XPO teams  invested significant resources in fixing known issues and covering more scenarios. While doing this, we have rewritten the old mechanism of persistent interface entities generation.

Registering entities As Alias

One of the key features of this rewrite is a new entities registration mode - so-called AsAlias mode. It is important for this blog to remind you what  an “entity” is in terms of DC. Here and in the future, by “entity” we mean a persistent interface or domain component, representing a final business entity (business model if you want). Although, domain components are often composed of several components (sorry for the tautology), not every domain component can be called an “entity”. This is again only the registered domain component used in your final application. I hope that now, we are done with the terms and can continue.clip_image002

Registering an entity as alias means that during the code generation, a single implementation class will be physically generated for it. Hence, all queries to XPO from this class will be served as for a regular XPO class. Furthermore, only one table will be created in the database for such entity! Let’s demonstrate this with the help of a concrete example.

I think that is enough theory for now. I will take a test case from one of my Code Central examples (E2829 - How to generate and assign a sequential number for a business object within a database transaction, while being a part of a successful saving process) and describe it more easily:

  1: using DevExpress.ExpressApp.DC;
  2: using DevExpress.Persistent.Base;
  3: using DevExpress.Persistent.Validation;
  4: 
  5: namespace GenerateUserFriendlyId.Module.BO {
  6:     public interface ISupportSequentialNumber {
  7:         long SequentialNumber { get; set; }
  8:     }
  9:     [DomainComponent]
 10:     public interface IBaseDomainComponent : ISupportSequentialNumber  { }
 11: 
 12:     [DefaultClassOptions]
 13:     [DomainComponent]
 14:     [XafDefaultProperty("Title")]
 15:     [ImageName("BO_Note")]
 16:     public interface IDocument : IBaseDomainComponent {
 17:         [Calculated("concat('D', ToStr(SequentialNumber))")]
 18:         string DocumentId { get; }
 19:         [RuleRequiredField("IDocument.Title.RuleRequiredField", DefaultContexts.Save)]
 20:         [FieldSize(255)]
 21:         string Title { get; set; }
 22:         [FieldSize(8192)]
 23:         string Text { get; set; }
 24:     }
 25: }

As you see, here I have one base domain component – IBaseDomainComponent, and another one – IDocument, descending from it (ISupportSequentialNumber is not domain component and just a pure interface, which we will not discuss here).

Previously, if I had registered my IDocument component:

  1: ...
  2: public override void Setup(XafApplication application) {
  3:     base.Setup(application);
  4:     if (!XafTypesInfo.IsInitialized) {
  5:         XafTypesInfo.Instance.AddEntityToGenerate("Document", typeof(IDocument), typeof(BasePersistentObject));
  6:     }
  7: }
  8: ...
  9: [NonPersistent]
 10: public abstract class BasePersistentObject : BaseObject, ISupportSequentialNumber { ... }
 11: ...

I would have received the following database structure:

clip_image004

Take special note that 5 tables would have been generated in this situation:

  • a single table for a registered entity (dbo.Document);
  • two separate tables to hold data of each domain component (dbo.IBaseDomainComponentClass & dbo.IDocumentClass);
  • two link tables used to establish relations between domain component data and entities (these are the expanded dbo.IBaseDomainComponentClassDocument and dbo.IDocumentClassDocument).

At first glance, this may look like overkill for such a trivial case, but it is inevitable if you want to support multiple inheritance and other DC features. However, in reality, multiple inheritance (some people out there consider it to be bad practice) is not needed in many cases. Or, it can be easily avoided by designing your business entities more carefully. We think that the majority of real cases are exactly those, and so we have made it possible to utilize a simpler database structure for them + other benefits that could not be used previously.

Below is the NEW way of registering the business entity I was talking about above:

  1: ...
  2: public override void Setup(XafApplication application) {
  3:     base.Setup(application);
  4:     if (!XafTypesInfo.IsInitialized) {
  5:         XafTypesInfo.Instance.RegisterEntity("Document", typeof(IDocument), typeof(BasePersistentObject));
  6:     }
  7: }
  8: ...
  9: [NonPersistent]
 10: public abstract class BasePersistentObject : BaseObject, ISupportSequentialNumber { ... }
 11: ...

Using this new mode helps me get the following database structure for my domain components definitions above:

clip_image006

If we dig more and see the auto-generated code for this entity (you can do this either by setting a breakpoint into the DevExpress.ExpressApp.DC.Xpo.TypeGenerator.GetCode method or by inspecting the generated cache DcAssembly.dll via Reflector), we will see what it looks like:

  1: ...
  2: public class Document : BasePersistentObject, IBaseDomainComponent, IDocument, ISupportSequentialNumber, ... { 
  3: ...

I intentionally omitted other XPO service stuff in the Document class declaration for the sake of simplicity. My main goal was to demonstrate that if an entity is registered AsAlias, a true class will be created behind the scenes, and this class will support all interfaces from the original domain component and its inheritance chain. Since it is a true class, an inevitable constraint comes from it - multiple inheritance is not available for “aliased” interfaces.

Before you are completely scared off and disappointed by this fact, I would provide quick clarification on it. Below, the allowed and illegal inheritance chains are demonstrated (take into account that A, B, C – are domain components registered AsAlias in your application):

A : B
B : C

or

A : B
C : B
– Both are allowed, because after generating entities there will be always a single base entity or a single inheritance chain.

A : B, C – Illegal.

Starting from 11.1, AsAlias mode is used by default, and you will receive a warning message from the deprecated AddAntityToGenerate method. You will have to either use the new RegisterEntity method and AsAlias mode or explicitly tell XAF that you want to use the old registration mode and its peculiarities.

There are still some known issues and suggestions…

Although the new AsAlias mode has greatly helped us in resolving old known issues (such as lack of server mode support, incorrect work on the Web, etc.), there are still some known issues, which we need to sort out before releasing the Domain Components technology. I separated the remaining problems into two categories, for convenience.

The first category consists of items that cause problems under certain scenarios. Those will certainly be resolved in the next minor releases, and it is sometimes even possible to workaround them in the current version. Take special note that some of these items are already NOT problems in AsAlias mode (marked in italic).

In the second category there are suggestions, based on the feedback we received from our customers. Implementing them can make the work with DC better, more convenient, but without these improvements DC can still be used normally by developers in all scenarios. Some suggestions are unique and even not present for pure persistent objects.

So, here we go:

Issues:

  • Improve support of domain components in built-in modules: System Windows Forms (support the ICategorizedItem interface), Audit Trail (make it possible to customize audit trail settings), Validation (support Rule Unique validation rule), Clone Object, Scheduler (support recurring events), etc.;
  • Support filtering by criteria, containing a key value (e.g. @CurrentUserId);
  • Support selection in the Web List Editors for unregistered base domain components* (already works in the AsAlias mode);
  • Cannot filter by the ObjectType and other XPO service fields (already works in the AsAlias mode).

Suggestions

  • Make it possible to supply a custom domain logic before deleting an object (OnDeleting);
  • Make it possible to supply a custom domain logic after an associated collection is changed (AfterListChanged);
  • Make it possible to supply a custom domain logic before a property getter or setter is executed (BeforeXXX);
  • Make it possible to mark a property as index (analog of the XPO’s IndexedAttribute);
  • Support multiple inheritance for base interfaces, containing a property with the same name;
  • Support medium trust environments.

* By unregistered base domain components we mean domain components that are parts of an entity, but are not registered as an entity. In our case, this is the IBaseDomainComponent interface.

Please note that I took only most popular customers suggestions and core issues, which are causing other side-effects or malfunctioning. So, if you are are aware of an issue that is not in this list, it is possible that it is caused by one of the core issues listed above. Feel free to verify this with Support to be sure. We will be glad to give you updates on this.

And finally, I want to announce one important thing, which I presume many of you want to hear: we hope to fix all the issues above in the next minor updates. Please stay tuned.

As always, we look forward to hearing your thoughts. Please do not hesitate to contact our Support Team if you encounter problems with certain scenarios using Domain Components or wish to propose an improvement.

Related help links:

Happy XAFingclip_image002

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.
No Comments

Please login or register to post comments.