In this document you can information regarding our database model generation and usage.

Current Implementation

Project Structure (Models)

In OneDealer's solutions under the project One.Dealer, in the path Models → OneDealerEntities there is the new models implementation .

  • One.Dealer

    • Models
      • OneDealerEntities
        • Extensions
          Here we can add extension methods on models.
        • OneDealer
          Models regarding OneDealer Entities (all the "IDMS_" models) 
        • SAPB1
          Models regarding SAP B1 Entities (BP, CP, User, etc)
        • Views
          Models regarding all the views we use
        • XIS
          Models regarding XIOMA's entities (all the "XIS_" & "XAS_")
        • OneDealerEntitiesContext
          The context contains the ORM reference to the entity
        • OneDealerEntitiesContextStoredProcedures
          This class contains the classes declarations of the stored procedures

Note:
We also make use of Partials folder, when we want to enhance the info of a model,
but it takes no part in the query operation.
For example: EmployeeInfo model has a read only property called FullName, 
which is the concatenation of FirstName and LastName

Create new model

All the existing models have been created with the help of T4 models generation provided in ORM we use Linq2db .

From now on we have two(2) ways to create a model:

  • Manually
  • Auto generated

Manual Process

  1. Create the table in the database
  2. Create the class in the related folder under the "OneDealerEntities".
    if it is OneDealer model, under the "OneDealer", etc.
  3. Name the class with the desired name and add the related data table columns as class properties
    1. Class must inherit form BusinessData class
    2. Namespace should be One.Dealer.Models.Entities
  4. Associate with Linq2db ORM by adding the necessary attributes - example
    1. Above the class declaration add the attribute [Table("CREATED_TABLE_NAME")]
    2. Above each property add the attribute [Column] providing also all the related to the table field information
      1. Table column name
      2. Data Type (NVarchar, Int16, Decimal)
      3. Length
      4. Nullable (it is nullable)
  5. Add the newly created class to OneDealerEntitiesContext as following
    public ITable<CLASS_NAME> PLURAL_OF_CLASS_NAME { get { return this.GetTable<CLASS_NAME>(); } }

Database objects

In general we have 3 different DB objects:

  1. DB tables (POCOs)
    1. Filepath at OneDealer solution: Application/One.Dealer/Models/OneDealerEntities/OneDealer (C# Models for DB Tables, MAIN/DEALER DB)
      1. Namespace: One.Dealer.Models.Entities
    2. Filepath at OneDealer solution: Core/One.Core/Models/OneDealerCommonEntities/OneDealer (C# Models for DB Tables, COMMON DB) 
      1. Namespace: One.Core.Models.Entities
  2. DB views
    1. Filepath at OneDealer solution: Application/One.Dealer/Models/OneDealerEntities/Views (C# Models for DB Views, MAIN/DEALER DB)
    2. Namespace: One.Dealer.Models.Views{}
    3. A DB view is a virtual table based on an SQL query referring to other tables in the database. A view stores an SQL query that is executed whenever you refer to the view.
  3. Stored Procedures
    1. Namespace: One.Dealer.Models.StoredProcedures 
    2. Filepath at OneDealer solution: Application/One.Dealer/Models/Partials/OneDealerEntitiesContextStoredProcedures.cs (C# Models for DB Stored Procedures, MAIN/DEALER DB)
    3. A stored procedure is a prepared SQL code that you can save, so the code can be reused over and over again. So if you have an SQL query that you write over and over again, save it as a stored procedure, and then just call it to execute it. You can also pass parameters to a stored procedure, so that the stored procedure can act based on the parameter value(s) that is passed

Code-related Database details

How to know which entity exists at the Dealer DB or the Common DB: 

  1. Comon DB entity: The namespace is One.Core.Models.Entities 
  2. Dealer DB entity: The namespace is One.Dealer.Models.Entities

When creating a new table/view (regarding the main/dealer DB):

  1. if it is a table, add a file here: ~\One.Dealer\Models\OneDealerEntities\OneDealer\Model.cs
  2. if it is a view, add a file here: ~\One.Dealer\Models\OneDealerEntities\Views\Model.cs
    1. Then go to ~\One.Dealer\Models\OneDealerEntities\OneDealerEntitiesContext.cs and add a public property of the table/view, similar to the others
    2. Then go to ~\OneDealer.Infrastructure.DependencyInjection\GeneratedBindingsModule.cs and add for the table/view, similar to the others


SAP B1 - Object Tables

If the class we created represents an object table of SAP B1 that means that this entity should be accessed through Service Layer call.

We need to make a last step.

In SAPB1DAL.cs (PATH: $OneDealer\Dev\Source\One.Dealer\One.Dealer\Repositories\SL\SAPB1DAL.cs)

  1. find the ServiceLayerObjectNameConvension dictionary
  2. add the table name and the name convention which was created in OUDO

This implementation is under investigation whether can be better. 

For example, we can create a custom attribute in the class that indicates that it is a Service Layer Entity

SQL to C# class

If you have a lot of tables/fields there are some tools online that can be helpful.

Sql 2 Object is an example, which converts the result of a SQL query to c# class.

It is based on the logic described here.

BusinessPartner
namespace One.Dealer.Models.Entities
{
	using System;
	using System.Collections.ObjectModel;

	using LinqToDB;
	using LinqToDB.DataProvider;
	using LinqToDB.DataProvider.SapHana;
	using LinqToDB.Mapping;

	using One.Core.Data;
	using One.Dealer.Models.Views;

	using OneCore.Infrastructure.Interfaces.DAL;

	[Table("OCRD")]
	public partial class BusinessPartner : BusinessData
	{
		[Column(              DataType=DataType.NVarChar,  Length=15),           PrimaryKey,  NotNull] public string    CardCode                     { get; set; } // NVARCHAR(15)
		[Column(              DataType=DataType.NVarChar,  Length=100),             Nullable         ] public string    CardName                     { get; set; } // NVARCHAR(100)
		[Column(              DataType=DataType.NVarChar,  Length=1),               Nullable         ] public string    CardType                     { get; set; } // NVARCHAR(1)
		[Column(              DataType=DataType.Int16,     Length=5),               Nullable         ] public int?      GroupCode                    { get; set; } // SMALLINT
		[Column("CmpPrivate", DataType=DataType.NVarChar,  Length=1),               Nullable         ] public string    CompanyPrivate               { get; set; } // NVARCHAR(1)
		[Column(              DataType=DataType.NVarChar,  Length=100),             Nullable         ] public string    Address                      { get; set; } // NVARCHAR(100)
		
	}
}


Now we are ready to use the new database table and model.

Auto generated Process

The auto generated procedure is similar to the previous implementation we had.

The main differences are 

  • It is generated a common database model for Hana and Service Layer, in contrast to the previous implementation which was generating two models (OneDealer Entities & Proxies)
  • The Service Layer calls are being made through HTTP calls (web requests) and not through WCF service reference (DataService)


Prerequisites

Visual Studio 2019. T4 models make use of C# 7.3


How to run the cycle of models for the auto generated process:

  1. open project solution in the following TFS path
    $/RC One/Tests/OneDealer.CodeGenerator
  2. In the "GenerateTables.ttinclude" add the desired Table or View name
  3. In the "GenerateNameConvensions.ttinclude", if needed, add the naming convention in the dictionary, for example OCRD to BusinessPartner alongside with a description
  4. If it is a Service Layer table, you should update the service reference under the project "OneDealerEntityConversion"
    1. Login to service layer though a http client (eg Postman)
    2. get the metadata info ({SL BASE URL}/b1s/v1/$metadata)
    3. check out "service.emdx" under "Connected Services" > "HanaServiceLayerProcies"
    4. Open the service.edmx in a notepad and paste the response of the $metadata call
    5. Save and close the file
  5. Right click to "OneDealerEntities.tt" and select "Run Custom Tool"
  6. After some time (it depends on the network and the workload of HANA on dev server, but approximately 20 minutes from our PCs in the office), the T4 tool will have produced the models.
    1. Models should be displayed with an explanation mark under the "OneDealerEntities.tt".
      The reason is that the models have been transferred under the "OneDealerEntities" folder as excluded from the project files.
      Refresh the "OneDealerEntities" folder in order to see the generated models.
  7. Build the solution to see if there are any errors.
  8. In OneDealer's TFS path for One.Dealer project, find the "OneDealerEntities" folder and check out the whole folder along with the files under it.
    1. Refresh the file "OneDealerEntities.tt" and include into the solution the newly generated models under the "OneDealerEntities" folder.
    2. Copy the generated files from OneDealer.CodeGenerator to the physical path of the "OneDealerEntities" in One.Dealer project

Behind the scenes

In depth description of the auto generated process


Previous Implementation

Describe the previous implementation




Alternative way to autogenerate DB models

Another way to create the C# models (instead of manually creating them by copying another class to have reference on what to add inside) for the tables and views is to call the stored procedure

  1. For tables
    1. CALL "IDMS_UTILITY_OBJECT2CSHARPCLASS_SP"('@TABLE_NAME', 0)
  2. For views
    1. CALL "IDMS_UTILITY_OBJECT2CSHARPCLASS_SP"('VIEW_NAME', 1)













Write a comment…