Data service

In some situations the methods in the domain services that exists will not fulfill the requirements for the function that should be built. One example can be querying for a specific record based on a field value or performing a batch manipulation.

Batching

This is used when you have multiple entities that should be persisted in one batch. If the batch is failing due to a business rule, the full batch is cancelled.

A batch can be mixed with different type of entities and different type of operations, for example create, update and delete.

using System;
using Litium.Data;
using Litium.Products;
public class BatchingExample
{
    private readonly DataService _dataService;
    private readonly BaseProductService _baseProductService;

    public BatchingExample(DataService dataService, BaseProductService baseProductService)
    {
        _dataService = dataService;
        _baseProductService = baseProductService;
    }

    public void Main()
    {
        var baseProduct2Delete = _baseProductService.Get("ArticleNumber_to_delete");
        var fieldTemplateSystemId = baseProduct2Delete.FieldTemplateSystemId;

        var baseProduct = new BaseProduct("new_articlenumber", fieldTemplateSystemId) { SystemId = Guid.NewGuid() };
        var variant = new Variant("new_variant_articlenumber", baseProduct.SystemId);

        using (var db = _dataService.CreateBatch())
        {
            db.Delete(baseProduct2Delete);

            db.Create(baseProduct);
            db.Create(variant);

            db.Commit();
        }
    }
}

Querying

Query information with data service is bypassing the caches. You should not use it without a cache if the result is to be used on public pages for visitors.

Querying can be used to query one type of entity at a time. There is support for fetching the entities or only the entities' system id. There is also support for count, skip and take.

An entity can have different options that is set when the query is created. For example when you query the base product you can automatically also get hits when a variant for the base product is matching the criteria.

using System.Collections.Generic;
using System.Globalization;
using Litium.Data;
using Litium.Data.Queryable;
using Litium.Products;
using Litium.Products.Queryable;

public class QueryingExample
{
    private readonly DataService _dataService;

    public QueryingExample(DataService dataService)
    {
        _dataService = dataService;
    }

    public void Main()
    {
        using (var query = _dataService.CreateQuery<BaseProduct>(opt => opt.IncludeVariants()))
        {
            var q = query.Filter(filter => filter
                .Bool(boolFilter => boolFilter
                    .Must(boolFilterMust => boolFilterMust
                        .Field("MyField", "eq", "MyValue")
                        .Field("MyField2", "neq", "MyValue"))
                    .MustNot(boolFilterMustNot => boolFilterMustNot
                        .Id("neq", "my_new_articlenumber"))))
                .Sort(sorting => sorting
                    .Field("MyField3", CultureInfo.CurrentCulture, SortDirection.Descending));

            int totalRecords = q.Count();
            List<BaseProduct> result = q
                .Skip(25)
                .Take(20)
                .ToList();
        }
    }
}

Different operators are avaliable to different fields, these can be listed by getting the field type, example:

private void GetFieldOperations(FieldDefinition fieldDefinition, FieldTypeMetadataService fieldTypeMetadataService)
{
    var fieldTypeMetadata = fieldTypeMetadataService.Get(fieldDefinition.FieldType);
    var fieldType = fieldTypeMetadata.CreateInstance(fieldDefinition);
    var operatorsString = fieldType.Operators.Select(o => o.Operator).Aggregate((a, b) => $"{a}, {b}");
    this.Log().Info($"Operators for {fieldDefinition.FieldType}: {operatorsString}");
}