When working with MDM dictionaries in the object navigator one can create attributes with the types: String, Integer, Real, DateTime, Data, Logical, and Long Text. The specified types meet basic requirements for storing the values that can be viewed and edited if required. If each dictionary element should store more complex structures, for example, files, images, and so on, one should modify dictionary structure on application level.
Each MDM dictionary is based on a table, dictionary attributes are linked with table fields. Tables support more data types, which fields can have. An attribute with the DbDataType.Blob type can be added to MDM dictionary from application code. In this case, the corresponding field with the Binary data type will be created in the table. Fields with the Binary data type are custom data types, work with them is executed via streams. For details see the Working with Fields That Have Custom Data Type article.
Consider the example of working with binary data in MDM dictionary attributes. To execute all further examples, add links to the IO, Metabase, and Rds system assemblies. The procedure for creating an attribute with binary data type in MDM dictionary structure:
/// <summary>
/// Add an attribute with binary data type to MDM dictionary
/// </summary>
/// <param name="RdsId">MDM dictionary identifier in repository</param>
/// <param name="AttrId">Identifier of created attribute for storing binary data</param>
Sub AddBlobAttributeInRds(RdsId: String; AttrId: String);
Var
Mb: IMetabase;
RdsDict: IRdsDictionary;
Attrs: IRdsAttributes;
Attr: IRdsAttribute;
Begin
Mb := MetabaseClass.Active;
// Open dictionary for edit
RdsDict := Mb.ItemById(RdsId).Edit As IRdsDictionary;
Attrs := RdsDict.Attributes;
If Attrs.FindById(AttrId) <> Null Then
//If attribute already exists, do not add a new one
Debug.WriteLine("Attribute with identifier " + AttrId + " already exists in MDM dictionary");
Return;
End If;
// Add an attribute
Attr := Attrs.Add;
Attr.Id := AttrId;
Attr.Name := AttrId;
Attr.DataType := DbDataType.Blob;
// Save changes
(RdsDict As IMetabaseObject).Save;
Debug.WriteLine("An attribute with the following identifier is created in MDM dictionary " + AttrId);
End Sub AddBlobAttributeInRds;
As input parameters, one sends MDM dictionary identifier in the repository and identifier of created attribute. If attribute with the specified identifier already exists in the dictionary, the procedure finishes without any additional actions.
Specify a stream as a value of attribute with binary data type. The stream can be linked to the file or created and filled with data stored in computer memory. The basic interface for working with streams is the IIOStream interface contained in the IO assembly.
The following function creates a new MDM dictionary element, enters name and value of attribute with binary data type. Dictionary identifier, binary attribute identifier, and full path to the file that will be saved to the binary attribute are sent as input parameters. The function results in the key of the created element:
/// <summary>
/// Add a new element to MDM dictionary and write file as a value for
/// attribute with binary data type
/// </summary>
/// <param name="RdsId">MDM dictionary identifier in repository</param>
/// <param name="AttrId">Identifier of attribute that has binary data type</param>
/// <param name="FilePath">Full path and name of the file that will be loaded as a binary attribute value</param>
/// <returns>Key of the new element created in MDM dictionary</returns>
Function SaveFileInBlobAttribute(RdsId: String; AttrId: String; FilePath: String): Integer;
Var
Mb: IMetabase;
DictInst: IRdsDictionaryInstance;
Data: IRdsDictionaryElementData;
Attrs: IRdsAttributesInstance;
Stream: IFileStream;
NewElementKey: Integer;
Begin
Mb := MetabaseClass.Active;
// Open MDM dictionary
DictInst := Mb.ItemById(RdsId).Open(Null) As IRdsDictionaryInstance;
Attrs := DictInst.Attributes;
// Attribute data for creating a new element
Data := DictInst.CreateElementData;
// Specify file path and name as element name
Data.Attribute(Attrs.FindById("NAME").Key) := FilePath;
// Create a stream related to file
Stream := New FileStream.Create(FilePath, FileOpenMode.Read, FileShare.DenyNone);
Stream.Position := 0
// Specify the stream as a binary attribute value
Data.Attribute(Attrs.FindById(AttrId).Key) := Stream;
// Add a new element to MDM dictionary root
// Key of new element will result from function execution
NewElementKey := DictInst.Insert(-2, data);
Dispose Stream;
Return NewElementKey;
End Function SaveFileInBlobAttribute;
In the platform interface attributes with binary data type are not displayed for dictionary elements. Values of these attributes are unavailable for users. A binary attribute is written and read to a stream. The IIOStreamClass.FromVariant static method is used to read value.
The following procedure reads a file from binary attribute of the specified element and saves the obtained file on the disk. Dictionary identifier, binary attribute identifier, element key, full path and file name are sent as input parameters.
/// <summary>
/// Read file from binary attribute of element and save to new file on the disk
/// </summary>
/// <param name="RdsId">MDM dictionary identifier in repository</param>
/// <param name="AttrId">Identifier of attribute that has binary data type</param>
/// <param name="ElementKey">Key of the element, from which attribute the file is read</param>
/// <param name="NewFilePath">Path and name of new file, to which file from binary attribute will be saved</param>
Sub LoadFileFromBlobAttribute(RdsId: String; AttrId: String; ElementKey: Integer; NewFilePath: String);
Var
Mb: IMetabase;
DictInst: IRdsDictionaryInstance;
Data: IRdsDictionaryElementData;
NewFile: IFileStream;
Stream: IIOStream;
Begin
Mb := MetabaseClass.Active;
// Open MDM dictionary
DictInst := Mb.ItemById(RdsId).Open(Null) As IRdsDictionaryInstance;
// To load custom attribute values one needs to set FetchAll=True
DictInst.FetchAll := True;
// Get attribute data of element with the specified key
Data := DictInst.Elements.Data(ElementKey);
// Read file from attribute value
Stream := IOStream.FromVariant(Data.Attribute(DictInst.Attributes.FindById(AttrId).Key));
Stream.Position := 0;
// Create a new file, to which file from element attribute will be saved
NewFile := New FileStream.Create(NewFilePath, FileOpenMode.Create, FileShare.DenyNone);
NewFile.Position := 0;
NewFile.CopyFrom(Stream, Stream.Size);
// Release the streams. The new file will be saved and unlocked
Dispose Stream;
Dispose NewFile;
End Sub LoadFileFromBlobAttribute;
The example of use of all above specified procedure/functions. Executing the example requires that the repository contains an MDM dictionary with RDS_DICT identifier. The file system should contain the d:\Work\1.dat file.
Sub UserProc;
Const
RdsId = "RDS_DICT";
BlobAttrId = "DATA_ATTR";
Var
NewElementKey: Integer;
Begin
// Add an attribute to MDM dictionary
AddBlobAttributeInRds(RdsId, BlobAttrId);
// Create an element and load file as a binary attribute value
NewElementKey := SaveFileInBlobAttribute(RdsId, BlobAttrId, "d:\Work\1.dat");
// Read binary attribute value and save contents to new file
LoadFileFromBlobAttribute(RdsId, BlobAttrId, NewElementKey, "d:\Work\new.dat");
End Sub UserProc
See also: