Monday, August 3, 2009

Storing business objects in EPiServer

I recently had a discussion with someone about how best to store collections in EPiServer, such as RSS feeds, advertisements, frequently asked questions, customer details etc. Here are my thoughts...

Using custom properties

If you wanted to display a collection of objects on a page, then usually you might create a custom property with a suitable interface so that editors can add to, and maintain the list. You could then register this property for a particular page type - so that each page of this page type can have its own list, or as a dynamic property - so that it is available as a shared list, and available across multiple page types.

This probably makes the most sense. However, the problem with this is that there is often a lot of development that needs to be done, e.g.:

  • Developing a suitable editor for the collection (which might need to allow sorting, grouping, searching, validation etc.)
  • Developing the web control that will render the list from the serialised data.
  • Adding the more advanced features that your business might need, such as workflows for approvals, scheduling the inclusion and deletion of items from the list, security and so on.

Even if you are sure that you know exactly what your business requires, there is still the chance for scope creep, and a future of upgrades and maintenance.

Using pages

One of the ways to make your life easier is to create your collections as EPiServer pages. This instantly gives you a huge amount of the functionality you might require to manage the items. You will have the ability to:
  • Easily define the properties of the items through their page type
  • Add workflows such as approvals
  • Set up access for different users and groups with different privileges
  • Use the many EPiServer page list controls that are available to render the list

And your editors will be able to:

  • Perform the usual C.R.U.D. operations
  • Organise items in a list or hierarchy, with grouping and sorting.
  • Search for items etc. etc.

In short, EPiServer is designed to manage a large collection, and this is what it does well! Of course, an item (in these sorts of collections) is a kind of content that does not directly correlate to a page on a website, so it might seem a bit foreign to re-use this functionality. However, it is a simple matter make sure that no-one can browse to an item (which now has its own URL) by adding some redirection or error trapping logic to the load event of the item’s page type ASPX, or through an event handler on the BeginRequest event. Actually it might be good to have the ability to display a page per item, if you wanted to give editors a preview how the item might look when displayed in a list! :)

There are some down sides though. EPiServer makes some assumptions about your items. It thinks they are pages of a site! This means adding a huge amount of overhead to them. The database stores a lot of information about pages in EPiServer that you might not want, and this, combined with the fact that the relational model isn’t going to be entirely optimised for your needs, will make data access slower than it needs to be. The API used to get page data back from the database is optimised in certain ways (such as retrieving the properties of the page), but this won’t do you any good if you have related objects in your list. You will often need several database reads on each page request. Caching may only get you so far as well.

Nowhere can potential performance issues been seen better, than in the page tree in the EPiServer edit mode. Imagine if you had thousands, or even millions of items in your collection. This interface is not designed to support lists of this scale. Even when in optimised mode, if your items do not lend themselves nicely to being stored in a hierarchy, and end up all under one parent node, then the interface will eventually become unusable, and you’ll need to write your own.

With a large collection of pages, you may also face performance issues on individual page requests, since the default EPiServer URL provider will have to search through all of your pages to find the page ID which corresponds to the requested URL.

If performance and scale are issues for you then the last resort is to start...

Using a custom data access layer

In the end, creating your own tables and stored procedures etc, may be the way to go, since you have so much extra control over the functionality, but generally I wouldn’t recommend it unless you really need to. EPiServer has so much functionality that can be re-used, it would seem silly to me not to try.

Summary

To summarize, using pages for your business objects is often a very good solution which is quick to implement and easily adopted by your editors. But what you need to bear in mind is that EPiServer is not a content management system in the literal sense. ‘Page management system’ would be more accurate, and if you’re thinking of using pages to manage your collections, you need to be sure that performance not be a problem.

It would be nice to see EPiServer change (or expand) their architecture in the future for enterprise applications in need of managing more than just pages. Of course, for specific markets, products and plugins are already available (EPiServer Community for instance).

5 comments:

Ted Nyberg said...

As you said, using pages for storing data gives you everything you need for basic CRUD operations, but you also get caching, searchability and other things "for free".

However, if you do implement your own data access layer you may want to have a look at the PageProvider mechanism to include records as pages even if they're not actually stored as pages in the EPiServer database.

That way you can use much of the EPiServer API for working with your data. It requires an Enterprise license, though...

Joel said...

Great post Dave! I agree with Ted regarding using Page Providers. Hopefully EPi will make that option available for sites that doesn't have an enterprise license as well in the future so we can always have that option.

When going with the second alternative, using pages, you might also want to have a look at the Page Type Builder (pagetypebuilder.codeplex.com) project which will give you strongly typed property access and a more object oriented way of working with the pages.

Ben Morris said...

I think that it's important to bear in mind that EPiServer is a Web CMS, so isn't an appropriate repository for business objects [IMHO].

You *could* use custom properties and pages to encapsulate business objects and store them in the EPiServer database, but EPiServer is no enterprise content management system - it's just there to manage and serve up web content. It does manage web page data pretty well, but I have seen too many EPiServer implementations that try to shoe-horn business objects into page types and properties. It doesn't scale well and it can make for a very messy architecture.

I always consider the pluggable features of EPiServer when looking at integration with external business objects, e.g. Page providers, virtual path providers, membership\role providers, etc.

David Hunt said...

Thanks for the comments guys. I do agree with the use of Page Providers. My only gripe there is that they don't allow you to change the way pages appear in the edit mode tree sufficiently to make it scalable to thousands of pages.

Ben: You're quite right. I would only use pages as objects as a short term solution when a quick win is needed.

Unknown said...

Great post David! I had exactly these considerations for a similar problem, now I'm pretty sure which way is the best to go, thanks!

Post a Comment