-
Notifications
You must be signed in to change notification settings - Fork 14
Data and MetaData Objects
A DataObject is the fundamental building block in Harmony Core. DataObjects are usually generated by CodeGen from a structure defined in a Synergy repository and they inherit from Harmony.Core.DataObjectBase
. DataObjects are generated with metadata that communicates the size, type, and location (position in the record) of each of your fields to other parts of Harmony Core. You can read a more in-depth exploration of DataObject here.
In this topic:
- Data Objects and Their Classes
- Validation
- Out-of-Band Object Loading
- Data Object Metadata
- Generating a Data Object Class
Data objects are the fundamental elements of Harmony Core. Each data object represents a Synergy record and is defined by a class that mirrors the repository structure for that record. One of the main functions of the code in these classes is to manage Synergy data internally while exposing field properties as CLS types, which are useful in both Synergy applications and a wide variety of non-Synergy applications.
Data object classes are typically generated using a CodeGen template included in the harmonycore project template (see Generating a Data Object Class below). Each data object class is generated from a structure in a Synergy repository and inherits from Harmony.Core.DataObjectBase
, which implements the System.Icomparable
interface methods that enable data objects to be sorted. Generated object classes are optimized to ensure that these comparisons are as fast and type-accurate as possible. Additionally, each class wraps Synergy data so it can be efficiently serialized and deserialized, keeps track of whether data has changed, and stores the GRFA for the record when the data was accessed. (GRFAs are critical for most Entity Framework (EF) Core operations and are useful for implementing optimistic concurrency.) Metadata associated with data objects enables instances to be created quickly from Synergy data.
Each generated data object class invokes Harmony Core converters that convert data object properties to and from underlying repository structure types. When building Synergy .NET application components, you have access to the entire Microsoft .NET Framework. However, Synergy types such as alpha, decimal, and implied decimal are unknown to this framework, so converters (which are classes in the Harmony.Core.Converters
namespace) provide the ability to convert between standard Synergy types and .NET types. For example, converters convert Synergy alpha data to .NET String
data (and vice versa), and convert Y/N fields to Boolean
data (a common requirement for legacy code). Along with these basic types of converters, there are converters that handle string formatting—e.g., that convert Synergy decimal data to DateType
data and vice versa.
Data object validation is enabled by overriding the Validate
method for DataObjectBase
. Because data object classes are typically generated, it is important to implement validation in a partial class in a file you’ve added to the Services.Models
project (e.g., Services.Models\MystructureCustom.dbl). Validate
has the following signature:
public virtual method Validate, void
type, ValidationType
serviceProvider, @IServiceProvider
Note that Validate
takes a System.ComponentModel.IServiceProvider
, which can be used to get access to the following, among other things:
Harmony.Core.FileIO.IFileChannelManager
Harmony.Core.Context.IDataObjectProvider
Harmony.Core.Interface.IDataObjectTransactionContext
The first two (IFileChannelManager
and IDataObjectProvider
) are useful when you need to read from an ISAM file to perform validation steps. IDataObjectTransactionContext
can be used to validate properties in reference to other existing objects—e.g., to check all the data objects currently being modified to ensure some other object is also valid or is in some way related.
Your code should throw an exception for invalid objects. By convention, this should derive from System.ComponentModel.DataAnnotations.ValidationException
. For example:
import System
import System.Collections.Generic
import System.ComponentModel.DataAnnotations
import System.Text
import Harmony.Core
import System.Diagnostics
import Microsoft.Extensions.DependencyInjection
import Harmony.Core.Interface
import Harmony.Core.Context
. . .
public partial class Customer extends DataObjectBase
. . .
public override method Validate, void
type, ValidationType
serviceProvider, @IServiceProvider
proc
;For this example, we’ll get dbContext, IDataObjectProvider, and
;IDataObjectTransactionContext service objects for dependency injection.
data dbContext = serviceProvider.GetService<DbContext>()
data dataObjectProvider = serviceProvider.GetService<IDataObjectProvider>()
data fileChannelManager = dataObjectProvider.ChannelManager
data transactionContext = serviceProvider.GetService<IDataObjectTransactionContext>()
if(dbContext == ^null || fileChannelManager == ^null || transactionContext == ^null)
throw new Exception("Something was null")
;We’ll use tracing (System.Diagnostics.Trace) in this example to display
;a message when validation occurs:
Trace.WriteLine(string.Format("Validating Customer Object for operation type {0}", type))
;Simple validation:
if(this.City != "Tbilisi")
throw new ValidationException("City was not valid")
endmethod
Note the following:
-
System.Data.Entity.DBContext
cannot be used in validation operations because EF Core does not support recursive operations. - Validation will occur during the
DBContext.SaveChanges
operation prior to locking/writing/deleting operations.
For calculated fields or complex multi-part records that do not fit the EF Core relational model, you can override the LoadOwnedObjectsInternal
method for DataObjectBase
:
protected virtual method LoadOwnedObjectsInternal, void
serviceProvider, @IServiceProvider
proc
This method takes an IServiceProvider
that can be used to retrieve an IFileChannelManager
or IDataObjectProvider
service object. Using these services, you can efficiently load whatever data you might need from ISAM files. You can register additional services during DBContext.OnConfiguring
.
LoadOwnedObjectsInternal
is called during the EF Core provider’s materialization phase, just prior to registering the object with the EF Core state tracker.
Synergy record data is kept separately from the metadata generated for the record. This reduces the size of each data object and keeps the cost of object construction low. Harmony.Core.DataObjectMetadataBase
contains the lookups necessary to enable EF Core query models to be converted to Synergy Select operations.
DataObjectMetadataBase
also acts as a factory for DataObjectBase
derivatives. The ODataModel.tpl CodeGen template creates a static constructor for each data object that registers its metadata against a static type lookup in DataObjectMetadataBase
. This enables generic I/O handling classes like File I/O and the Harmony Core Entity Framework Provider to work without using reflection, even though those classes have no information on the types they will encounter until runtime.
A data object class can be generated using CodeGen with the ODataModel.tpl template, which generates the class from a Synergy repository structure. This CodeGen template is included in solutions created from the harmonycore project template (see Code Generation), and the regen.bat file (also included in the harmonycore template) is set up to automatically run CodeGen with the template. However, you can create your own CodeGen commands for this. For example, the following is for a structure named CUSTOMER:
codegen -s CUSTOMER -t ODataModel -n Services.Models -o Services\Models -r
-
Tutorial 2: Building a Service from Scratch
- Creating a Basic Solution
- Enabling OData Support
- Configuring Self Hosting
- Entity Collection Endpoints
- API Documentation
- Single Entity Endpoints
- OData Query Support
- Alternate Key Endpoints
- Expanding Relations
- Postman Tests
- Supporting CRUD Operations
- Adding a Primary Key Factory
- Adding Create Endpoints
- Adding Upsert Endpoints
- Adding Patch Endpoints
- Adding Delete Endpoints
-
Harmony Core Code Generator
-
OData Aware Tools
-
Advanced Topics
- CLI Tool Customization
- Adapters
- API Versioning
- Authentication
- Authorization
- Collection Counts
- Customization File
- Custom Field Types
- Custom File Specs
- Custom Properties
- Customizing Generated Code
- Deploying to Linux
- Dynamic Call Protocol
- Environment Variables
- Field Security
- File I/O
- Improving AppSettings Processing
- Logging
- Optimistic Concurrency
- Multi-Tenancy
- Publishing in IIS
- Repeatable Unit Tests
- Stored Procedure Routing
- Suppressing OData Metadata
- Traditional Bridge
- Unit Testing
- EF Core Optimization
- Updating a Harmony Core Solution
- Updating to 3.1.90
- Creating a new Release
-
Background Information