ORM architecture

ORM architecture

DWKit uses a special ORM engine that allows getting data represented as dynamic objects or strongly typed objects inherited from DbObject<T>, where T refers to the type of object. To request and update information in the database, you need information about what tables you should request, types of columns, and how to build joins. In other words, you need metadata. In DWKit this metadata is represented by an EntityModel object. You can get this information from three sources:

  • Using Data Model, which you can change and synchronize in the admin panel. In this case, you should request data object by the DataModel object name.
  • Using Form and data mapping, which can be edited in the admin panel. In this case, you should request data object by the Form name.
  • Using information from the attributes which mark properties of the class inherited from DbObject<T>.

In first two cases, getting a model is provided by MetadataToModelConverter static class, in the third case - by DbObject<T>.Model property. Below is an example of getting EntityModel from Data Model:

EntityModel userModel = await MetadataToModelConverter.GetEntityModelByModelAsync("SecurityUser");

In this case, the EntityModel provides access to the SecurityUser table in the database.

An example of getting the EntityModel from the Form:

EntityModel userModel = await MetadataToModelConverter.GetEntityModelByFormAsync("SecurityUserForm");

In this case, EntityModel provides access to SecurityUser table and additional data (for example, to collections), described in the form and data mapping.

Here's an example of getting EntityModel from DbObject<T>:

public class SecurityUser : DbObject<SecurityUser>
{
    [DbObjectModel(IsKey = true)]
    public Guid Id
    {
        get => _entity.Id;
        set => _entity.Id = value;
    }

    [DbObjectModel]
    public string Name
    {
        get => _entity.Name;
        set => _entity.Name = value;
    }

    [DbObjectModel]
    public string Email
    {
        get => _entity.Email;
        set => _entity.Email = value;
    }
}
EntityModel securityUserModel = SecurityUser.Model;

In this case, EntityModel provides access to SecurityUser table in the database. Table name and columns names match class name and properties names.

Thus, using EntityModel, you can request or update data. Usually, such operations are performed using DynamicRepository static object or using EntityModel instance. For example:

var userModel = await MetadataToModelConverter.GetEntityModelByModelAsync("SecurityUser");
var user = (await userModel.GetAsync(Filter.And.Equal(userId, "Id"))).FirstOrDefault();

or using class static methods, inherited from DbObject<T>. For example, using SecurityUser class, described above:

var user = await SecurityUser.SelectByKeyAsync(userId);

First approach is used to organize general business logic. For example, DWKit uses it to organize data sources for forms. Second approach is used to organize complicated and unique algorithms of business logic.

When requesting data, you can specify request parameters:

  • Filter object - filter (WHERE clause) in the request, for example, var filter = Filter.And.Equal(userId, "Id") - filter by column (property, attribute) Id.
  • Order object - sorting (ORDER BY clause) in the request
  • Paging object - specification of data page in the request.

You can also change or update data using the DynamicRepository object or using EntityModel. Upon data selection, you get objects of two types:

  • In case you used EntityModel to request data, you will get a list or a unique object, such as DynamicEntity. There are two ways of getting values of properties from them. For example, Email property.

    string email = (string)user["Email"];

    or using conversion to dynamic:

    var dynamicUser = user as dynamic;
    string email = user.Email;
  • In case you used DbObject<T> inheritor to request data, data will be strongly typed. For example, you can get User - as an object and get its Email property value.

    var user = await SecurityUser.SelectByKeyAsync(userId);
    string email = user.Email;