The content you're reading is getting on in years
This post is on the older side and its content may be out of date.
Be sure to visit our blogs homepage for our latest news, updates and information.
UPDATE: After the initial version of this blog post, we introduced some changes in Sitefinity, which required somewhat different code. Some people noticed this in the comments below. The blog post has been updated with code working for Sitefinity 4.1. You can always find a working code sample illustrating the topic in the latest release of the Products module in Sitefinity SDK.
As you know, Sitefinity relies heavily on the OpenAccess ORM for its data layer. We’ve provided an extensible model, in which you can plug a custom implementation for your storage mechanism, but all our modules use OpenAccess by default. That’s why we are excited to announce that we’re shipping a new version of OpenAccess with the 4.1 release.
There will be tons of benefits in this new version that we’ll announce later. For now, we want to bring your attention to a particular change we’re introducing with this upgrade - Fluent mappings for persistent classes. We’ve updated all of our built-in modules to use the new mappings, and all custom modules that use OpenAccess will have to do the same.
This means anyone who has created a custom Sitefinity 4.x module that relies on OpenAccess will need to make changes to their module before it is compatible with 4.1.
Let's get started...
To illustrate the value of fluent mapping support, let's look at how persistent classes were mapped until now. OpenAccess needs metadata to know how to generate tables from your persistent classes. In the current Sitefinity projects, there are two places where it gets the metadata from:
This is cumbersome for two reasons. First, you need to maintain both the code of the persistent class and the app.config file. Second, the only way to provide different mappings for a single class is to duplicate the whole mapping.
Let’s take the sample Products module from the Sitefinity SDK as an example. Its current mappings look like this:
<!--<extension key="db-table-name" value="sfex_product_urls" />-->
Fluent mappings address all of the above challenges. They provide a single place where all persistent classes are configured. Joshua Holt has created a series of videos introducing Fluent mappings in the OpenAccess ORM. I highly encourage you to watch those before you start changing your modules. Below, we’ll put the same concepts into the Context of a Sitefinity module.
With the newly introduced fluent mappings, all of the above is replaced with code. Instead of relying on a particular XML file, the framework calls a method that you write. You can then supply the mapping and include your own logic depending on the database (e.g. map something differently for Oracle). The steps you need to follow are the following:
This property provides runtime state information used by Sitefinity. You just need to have it – nothing fancy in the implementation, except an automatic getter and setter.
This method is called automatically and returns a MetadataSource object, containing all information about the mappings in the specific provider. The object will be of the type you implement in the last step. Here just create an instance by passing the context parameter.
MetadataSource GetMetaDataSource(IDatabaseMappingContext context)
ProductsFluentMapping : OpenAccessFluentMappingBase
var mappings =
var itemMapping =
itemMapping.HasProperty(p => p.Id).IsIdentity();
itemMapping.HasProperty(p => p.Price);
itemMapping.HasProperty(p => p.QuantityInStock);
itemMapping.HasAssociation<Telerik.Sitefinity.Security.Model.Permission>(p => p.Permissions);
itemMapping.HasProperty(p => p.InheritsPermissions);
itemMapping.HasAssociation<Telerik.Sitefinity.Security.Model.PermissionsInheritanceMap>(p => p.PermissionChildren);
itemMapping.HasProperty(p => p.CanInheritPermissions);
itemMapping.HasAssociation(p => p.Urls).WithOppositeMember(
itemMapping.HasAssociation<Telerik.Sitefinity.Workflow.Model.Tracking.ApprovalTrackingRecordMap>(p => p.ApprovalTrackingRecordMap);
var urlDataMapping =
This is the implementation of the mapping itself. All mappings inherit OpenAccessFluentMappingBase and override the GetMapping() method. In the sample Products module, we have separated its work in two calls, one for each persistent class. Everything you need to specify in a mapping has a corresponding method in the MappingConfiguration class. You can specify the name of the table, properties, any associations to other classes, inheritance configurations, etc. When developing a content-based module, they are going to be very similar to the mappings for Products in the above sample.
ProductsFluentMetadataSource : ContentBaseMetadataSource
var sitefinityMappings =
The metadata source is an object that you return in the GetMetadataSource method you implemented in the second step above. If you are building a custom module from scratch, you can directly create an instance of any class that derives from MetadataSource. However, when building content-based modules, most of the work has been done for you anyway. We’ve provided a way for you to reuse it – just create your own metadata source and inherit from ContentBaseMetadataSource. Then your only job is to override BuildCustomMappings() and add an instance of the mapping class you created in the previous step to the ones created in the base implementation (Generic Content).
Please note that all modules working with OpenAccess need to edit their project files and supply the correct path to the OpenAccess assemblies. For more information on this, refer to our documentation.
The source code for the new Products module mappings is available in the 4.1 SDK. Once you follow the steps above, your module should be ready for Sitefinity 4.1. Have these changes in mind before upgrading your projects to the release coming up next week. We’ll be available to help you if you have questions about the new OpenAccess version. We’re looking forward to seeing how you extend Sitefinity. Happy coding.
View all posts from The Progress Team on the Progress blog. Connect with us about all things application development and deployment, data integration and digital business.
Subscribe to get all the news, info and tutorials you need to build better business apps and sites
Copyright © 2019 Progress Software Corporation and/or its subsidiaries or affiliates.
All Rights Reserved.
Progress, Telerik, and certain product names used herein are trademarks or registered trademarks of Progress Software Corporation and/or one of its subsidiaries or affiliates in the U.S. and/or other countries. See Trademarks for appropriate markings.