Architecture of ELMA object model
General concept
ELMA object model is a set of classes, entities, enumerations, that can be used to define the business logic of the application. Under entity, a database object is implied. The main classes for working with the object model are located in the EleWise.ELMA.SDK assembly (EleWise.ELMA.Model namespace).
Components of ELMA object model are described below.
Metadata
Generally, metadata is a set of data items. Each item describes a specific element of the object model (e.g. entity type, enumeration).
You can use ELMA plugin for Visual Studio to create new types of entities. Main types of metadata are located in the EleWise.ELMA.Model.Metadata namespace. Metadata files have .md format (in fact, these are common XML files).
Below is an example of an entity’s metadata:
<?xml version="1.0" encoding="utf-8"?>
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" IsUnique="true">
<Uid>04d5bcbf-4288-4d95-9745-1ebd0d690bb3</Uid>
<Name>User</Name>
<DisplayName>User</DisplayName>
<Namespace>EleWise.ELMA.Model.Entities.Security</Namespace>
<Properties>
<PropertyMetadata xsi:type="EntityPropertyMetadata">
<Uid>9357aacc-d37f-497a-99f4-4a106765f8e1</Uid>
<Name>UserName</Name>
<DisplayName>Account</DisplayName>
<TypeUid>9b9aac17-22bb-425c-aa93-9c02c5146965</TypeUid>
<Settings xsi:type="StringSettings">
<FieldName>UserName</FieldName>
</Settings>
<Required>true</Required>
<Filterable>true</Filterable>
</PropertyMetadata>
<PropertyMetadata xsi:type="EntityPropertyMetadata">
<Uid>a1e9ab10-6dad-4a11-a190-8f9d11b9ed77</Uid>
<Name>Password</Name>
<DisplayName>Password</DisplayName>
<TypeUid>9b9aac17-22bb-425c-aa93-9c02c5146965</TypeUid>
<Settings xsi:type="StringSettings">
<FieldName>Password</FieldName>
</Settings>
</PropertyMetadata>
</Properties>
<Type>Interface</Type>
<ImplementationUid>18faf3ae-03c9-4e64-b02a-95dd63e54c4d</ImplementationUid>
<TableName>User</TableName>
<Filterable>true</Filterable>
</Entity>
The source code is automatically generated in C# with the types defined in metadata. In this case, the following code will be generated:
namespace EleWise.ELMA.Model.Entities.Security
{
/// <summary>
/// User
/// </summary>
[MetadataType(typeof(EntityMetadata))]
[EntityMetadataType(EntityMetadataType.Interface)]
[Uid("04d5bcbf-4288-4d95-9745-1ebd0d690bb3")]
[ImplementationUid("18faf3ae-03c9-4e64-b02a-95dd63e54c4d")]
public partial interface IUser : IEntity<long>
{
/// <summary>
/// Account
/// </summary>
string UserName { get; set; }
/// <summary>
/// Password
/// </summary>
string Password { get; set; }
}
}
NHibernate
ELMA uses NHibernate (ORM component) to interact with a database. To make NHibernate easier to work with, we added the following base functions to ELMA SDK:
- When you create an entity using the plugin for Visual Studio, the mappings are created automatically;
- Work with sessions in the object managers;
- For entity managers there is a base class, that provides the base methods for them (e.g. Load, Save, Find);
- All changes to the database are done within transactions. You can mark a manager’s method with TransationAttribute to make sure that the transaction will be committed after the method is executed.
Managers
A manager is a service used to interact with the object model elements. Usually, we use managers to work with entities (for more info see Entity managers).
Extending object model
In ELMA, you can extend the object model. This allows creating additional modules with their own entities or adding properties to entities from other modules. This is possible because in ELMA extendable interfaces for entities are used (for more info see Entities).
Modules with object models
You can create objects in any assembly with the EleWise.ELMA.Model.Attributes.ModelAssemblyAttribute attribute.
You can add this attribute in 2 ways:
1. Modify AssemblyInfo.md\AssemblyInfo.cs by adding the following code:
[assembly: EleWise.ELMA.Model.Attributes.ModelAssembly()]
2. Using the ELMA plugin for Visual Studio, add new ELMA Assembly Info item and select The assembly contains models option:
Entities
See Entities.
Working with metadata
There is a service for working with metadata: EleWise.ELMA.Model.Services.IMetadataRuntimeService. Please check its description in API help.
namespace EleWise.ELMA.Model.Services
{
/// <summary>
/// Service interface for metadata information
/// </summary>
[ExtensionPoint]
public interface IMetadataRuntimeService
{
/// <summary>
/// Get the type according to the unique identifier
/// </summary>
/// <param name="uid">Type UID</param>
/// <param name="loadImplementation">Whether tp load the implementation metadata, if the specified type is "Interface"</param>
/// <returns>Type</returns>
Type GetTypeByUid(Guid uid, bool loadImplementation = true);
/// <summary>
/// Get the metadata according to the unique identifier
/// </summary>
/// <param name="uid">Metadata UID</param>
/// <param name="loadImplementation">Whether tp load the implementation metadata, if the specified type is "Interface"</param>
/// <returns>Metadata</returns>
IMetadata GetMetadataByUid(Guid uid, bool loadImplementation = true);
/// <summary>
/// Register type
/// </summary>
/// <param name="type">Type</param>
void RegisterType(Type type);
/// <summary>
/// Get the list of metadata
/// </summary>
/// <returns>The list of metadata</returns>
IEnumerable<IMetadata> GetMetadataList();
/// <summary>
/// Get a description of the data type according to its unique identifier. If the discription is not found - null
/// </summary>
/// <param name="typeUid">Data type UID</param>
/// <returns>Description of data type</returns>
ITypeDescriptor GetTypeDescriptor(Guid typeUid);
/// <summary>
/// Get a description of the data type according to CLR type. If the discription is not found - null
/// </summary>
/// <param name="runtimeType">CLR type</param>
/// <returns>Data type description</returns>
ITypeDescriptor GetTypeDescriptor(Type runtimeType);
/// <summary>
/// Get a description of the data type that can be used for the primary key, according to its unique identifier.If the discription is not found - null
/// </summary>
/// <param name="typeUid">Data type UID</param>
/// <returns>Data type description</returns>
ITypeDescriptor GetIdTypeDescriptor(Guid typeUid);