Skip to content

Latest commit

 

History

History

ViennaNET.Orm

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

An assembly containing an intermediary implementation for performing service operations

Key Entities

  • SessionFactoryProvider - performs the following functions:
  1. Configures the basic parameters of NHibernate.
  2. Registers entity mappings. Supports Fluent syntax.
  3. Based on 1 and 2 points creates SessionFactory.
  • ScopedSessionManager - provides the life cycle of NHibernate sessions within a web request. It is an analog of the Nhibernate session context. Created because none of the contexts is fully suitable for solving the problem.

  • EntityFactoryService - creates various wrappers for working with the repository. The created interfaces are abstracted from the type of storage.

  • EntityRepository - an abstract repository for working with the repository as a collection of objects. Contains additional infrastructure methods.

  • UnitOfWork - is an implementation of the "Unit of Work" template.

Instructions for use:

  1. Add a dependency on IEntityFactoryService to the class.
  2. Add the configuration file appsettings.json,
    "db": [
      {
        "nick": "default",
        "dbServerType": "DB2",
        "ConnectionString": 
            "Database = DBNAME; UserID = user_name; Server = servername: 50000; CurrentSchema = SCHEME;"
      },
      {
        "nick": "mssql",
        "dbServerType": "MSSQL",
        "ConnectionString": "Server = servername, 1433; Database = DBNAME; User ID = user_name;"
      }
    ]

For each connection to the database, a separate list item is created containing the following parameters:

  • nick - the name of the connection to the database. Unique identificator.
  • dbServerType - type of database to which the connection is made.
  • connectionString - connection string to the database

3a. If you just need to read the entity from the database, then just create a repository and call the Get method, passing the Id into it.

return _entityFactoryService.Create<Entity>()
                                .Get(message.Id);

3b. If you want to read database entities with filtering, you can use the LINQ query.

    return _entityFactoryService.Create<Entity>()
           .Query().Where(x => x.Status == EntityStatus.Processed && x.UpdateDate < DateTime.Today);

4a. In the event of an entity change, a unit of work must be created. Changes in the fields of an entity must occur in it.

     using (var unitOfWork = _entityFactoryService.Create())
     {
       var entity = _entityFactoryService.Create<Entity>().Get(message.Id);

       entity.DoStaff(message);

       unitOfWork.Commit();
     }

4b. If an entity is created, use the Add method to add it.

     using (var unitOfWork = _entityFactoryService.Create())
     {
       var entityRepository = _entityFactoryService.Create<Entity>();

       var entity = Entity.Create(message);

       entityRepository.Add(entity);

       unitOfWork.Commit();
     }

4c. The Add method, if there is an entity with the same identifier in the collection, will try to execute the Update request. If this behavior should be prohibited, you can use the Insert method, which in the same case will throw an exception.

  1. You can delete an entity using the Delete method.
     using (var unitOfWork = _entityFactoryService.Create())
     {
       var entityRepository = _entityFactoryService.Create<Entity>();

       var entity = entityRepository.Get(message.Id);

       entityRepository.Delete(entity);

       unitOfWork.Commit();
     }
  1. When processing in manually created tasks, it is additionally necessary to create scope sessions. Without this, exceptions will occur during operation.
    return await Task.Run(() =>
    {
      using (_entityFactoryService.GetScopedSession())
      {
        return _entityFactoryService.Create<Entity>()
                                    .Get(message.Id);
      }
    });
  1. For the correct operation of the entity must be registered in a limited context of the service. To do this, create a class in the assembly
    internal sealed class TestLogicsContext: ApplicationContext
    {
      public TestLogicsContext()
      {
        AddEntity<Card>();
        AddEntity<Product>("mssql");
      }
    }

and register it in the DI with the IBoundedContext interface.

    container.Collection.Append<IBoundedContext, TestLogicsContext>(Lifestyle.Singleton);

Executing SQL queries:

To create a SQL query to the database, you need to create a query class.

    internal class EntityDetailsQuery : BaseQuery<EntityDetailsItem>
    {
      private const string query = @"SELECT FIELD, ANOTHER_FIELD
              FROM SCHEME.ENTITY SE
              WHERE SE.WHERE_FIELD = :data";

      public EntityDetailsQuery(string data)
      {
        Parameters = new Dictionary<string, object>();
        Parameters["data"] = data;

        sql = query;
      }

      protected override EntityDetailsItem TransformTuple(object[] tuple, string[] aliases)
      {
        return new EntityDetailsItem(tuple[0].ToStringSafe(), (DateTime?)tuple[1]);
      }
    }

Next, you need to create a query executor and call it with the created instance of the command.

    var query = new EntityDetailsQuery("keyData");

    var customQueryExecutor = _entityFactoryService.CreateCommandExecutor<EntityDetails>();

    IEnumerable <EntityDetails> entityDetails = customQueryExecutor.CustomQuery(query);

Executing SQL commands:

To create an SQL command to the database, you need to create a command class.

    public class EntityCommand: BaseCommand
    {
      private EntityCommand()
      {
      }

      public static EntityCommand Create(int cnum)
      {
        return new EntityCommand
        {
          Parameters = new Dictionary<string, TypeWrapper>
          {
            {"P_CNUM", new TypeWrapper(cnum, typeof(int))}
          },

          Sql = "CALL SCHEME.ENTITY_COMMAND(:P_CNUM)"
        };
      }
    }

Next, you need to create an executor of commands and call it with the created instance of the command.

    var command = new EntityCommand(123456);

    var commandExecutor = _entityFactoryService.CreateCommandExecutor<EntityCommand>();

    commandExecutor.Execute(command);

Logging

Now ViennaNET.Orm use Microsoft.Extensions.Logging instead of ViennaNET.Logging (log4net). That means you should use standard configuration section for rule output logs with parameters you want, e.g.:

"Logging": {
    "LogLevel": {
        ...,
        "ViennaNET.Orm": "Information",
        "NHibernate": "Error",
        "NHibernate.Sql": "Debug",
    }
}

Useful options for LogLevel parameters:

  • To log SQL requests with parameters you should set log level of NHibernate.Sql to Debug
  • To log query execution time you should set log level of NHibernate.AdoNet.AbstractBatcher to Debug. Ad i logs you get ExecuteReader took X ms for query execution and DataReader was closed after X ms for data mapping