Documentation

Ucommerce includes full API reference documentation and lots of helpful articles to help you build your e-commerce site as effortlessly as possible.

Topics Payment Providers
v7.18

Extending Ucommerce entities

Imagine the scenario, where you need to register the name of the company your customers are working for.

Unfortunately not all Ucommerce entities supports definitions, so you cannot simply add a new text field to a customer definition.

A very direct way of handling this, would be to store the additional data in a new database table, and link it to a Customer by using the CustomerId value. Crude and simple, but effective. The downside is that you need to handle two classes: The normal customer entity and your "related data-entity" that holds the additional information as well.

Fortunately Ucommerce enables you to add that extra piece of information directly to the UCommerce.EntitiesV2.Customer object! The technique to do so, is a bit different, since entities in Ucommerce are mapped to the database using NHibernate.

To extend them, you need to tell NHibernate how to map the new fields to columns in the database. To do so you need to extend the existing mappings.

In the following example we will show how to extend the Ucommerce Customer entity with a new field called "ExternalIdentifier".

Creating the custom entity

The first thing to do, is creating the custom customer class, by inheriting from the standard customer.

    public class MyCustomCustomer : Ucommerce.EntitiesV2.Customer
    {
        //All properties mapped is required by NHibernate to be virtual
        public virtual string ExternalIdentifier { get; set; }
    }
    
    

Extend the NHibernate mappings

NHibernate supports two ways of mapping the inherited classes to database tables.

  • table-per-hierarchy (TPH)
  • table-per-class (TPC)

Below are examples using both these strategies.

Table per hierachy

Important! Please note that prior to Ucommerce version 6.7.3, you needed to make sure that your IContainsNHibernateMappings tag component was before the standard Ucommerce tag components in the registration of the session factory component.

Mapping all the classes in the inheritance hierachy to one class has the advantage of avoiding any additional database joins when the data is fetched. The downside is that you need to modify the existing Ucommerce table. This could potentially cause problems in an upgrade scenario, if changes to the default database schema conflicts with your custom changes.

NHibernate mappings

You need two new map classes.

In order to instruct NHibernate to use TPH, the mapping for the entity has to be overridden.

    
    public class CustomerMap : Ucommerce.EntitiesV2.Maps.CustomerMap
    {
        public CustomerMap()
        {
            DiscriminateSubClassesOnColumn("Type", (byte)0).Not.Nullable();
        }
    }
    
    

You also need a new sub class map for you custom fields.

    
       
       public class MyCustomCustomerMap : SubclassMap<MyCustomCustomer>
       {
           public MyCustomCustomerMap()
           {
               DiscriminatorValue(1);
               Map(x => x.ExternalIdentifier);
           }
       }
       
       

Adding custom columns to the Ucommerce database.

You need to add two new columns to the Ucommerce_Customer table, to get the example to work.

You need a new INT column called "Type". This is what NHibernate uses to distinguish between the different sub classes. Make sure to give all existing rows a value of 0. This marks them as being standard Customers. You also need a new NVARCHAR(255) column called "ExternalIdentifier", to hold your custom field value.

Table per class

Mapping the sub classes to individual tables has the advantage that it does not change any of the existing Ucommerce tables. The downside is that the tables needs to be joined when data is read. This can impact the overall performance of the solution.

NHibernate mappings

In this case, you only need one new map class.

    
    public class MyCustomCustomerMapTablePerClass : SubclassMap<MyCustomCustomer>
    {
        public MyCustomCustomerMapTablePerClass()
        {
            Table("Ucommerce_MyCustomCustomer");
            KeyColumn("MyCustomCustomerId");
    
            Map(x => x.ExternalIdentifier);
        }
    }
    
    

Adding a custom table to the Ucommerce database.

You need to add a new table, to hold the additional data for your custom fields.

For example like this.

    
    
    CREATE TABLE [dbo].[Ucommerce_MyCustomCustomer](
    	[MyCustomCustomerId] [int] NULL,
    	[ExternalIdentifier] [nvarchar](255) NULL
    ) ON [PRIMARY]
    
    

Registering an assembly tag component

Regardless of which strategy you have chosen, you need to register the new mappings in the IOC container, so the Ucommerce system can add them to NHibernate.

To instruct Ucommerce to add the new mappings found in your custom assembly, you need to create an assembly tag and register the component in the custom configuration file. Please see Save custom data in the database

Using the custom entity

You can create the new custom customer like this. Note: The usage does not depend on the chosen strategy.

    
               
               var myCustomer = new MyCustomCustomer();
    
               myCustomer.FirstName = "This";
               myCustomer.LastName = "Rocks";
    
               myCustomer.EmailAddress = "[email protected]";
    
               myCustomer.ExternalIdentifier = "Mr. Rocks";
    
               myCustomer.Save();
    
               

You can now read your new customer from the database.

    
    var repository = ObjectFactory.Instance.Resolve<IRepository<MyCustomCustomer>>();
    MyCustomCustomer customer = repository.SingleOrDefault(x => x.ExternalIdentifier == "Mr. Rocks");
    
    

Reading all Customers will also return the customers with the new MyCustomCustomer type.

    
    var customers = Customer.All();
    
    foreach (var c in customers) {
        // Check the type of customer.
        // The original customers will have type Customer. And the new ones will be of your custom type MyCustomCustomer.
    }