|
Key
This line was removed.
This word was removed. This word was added.
This line was added.
|
Comment:
Changes (1)
View Page Historyh4. Introduction
This section describes how to work with the Business Meta Model from Business Foundation (BF). For information on how to work with business objects refer to [ecf51devguide:Working with Entity Objects].
All classes are available in *Mediachase.BusinessFoundation.Data.Meta* and *Mediachase.BusinessFoundation.Data.Meta.Management* namespaces.
Business Meta Model defines elements: MetaType, MetaEnum, MetaClass, MetaField, Modules.
MetaType represents field type declarations: string, html text, numder, enums, file, image and etc. MetaType has all popular types and extend it with UI friendly types. For example instead of using one type of string, Business Meta Model has Short String, Long String, Html, Email, Phone number, etc. You can easily create a new MetaType based on system type or create custom.
MetaEnum represents enumeration. Enumeration can be single or multi select. When a new meta enum is created, new meta type is registered.
MetaClass represent a class. It contains a collection of meta fields. You can use a meta class to create an entity object. You can modify meta class fields (add, remove) at runtime. MetaClass can be extended with several cards, but only one card can be active in the entity object. Each card can has own field set.
For example: we created a new meta class Client, marked that meta class support cards and created three card "Regional Client", "Foreign Client" and "Partner" with own field sets. If we create a new client object without cards, only meta class fields are available but if you set the card property, the fields from the card will be available in the entity object automatically.
!worddaveebd14bc8bc7037aacec6a1271897e15.png|height=496,width=568!
BF supports 1-N, N-N and aggregation references between two meta classes.
Modules represent custom extensions. Modules can be installed in the system and activated in the meta class. Default modules are:
* *Change Tracking* \- adds a new field to meta class and registers user and date time of modification
* *History* \- save meta object modifications to history meta class
* *Localization* -- allows localized field value
h4. Initialization
The Business Meta Model uses a SQL Server database as data storage. To manually prepare the database, run "_SqlTables.sql_", "_SqlSp.sql_" and "_SqlInitialData.sql_" scripts. The scripts create the infrastructure for metamodel data storage.
*Note:* Only one Business Meta Model can exist in a database.
A *DataContext* object represents a unique entry point to Business Meta Model. When you create an instance of *DataContext*, Business Meta Model is loaded and all properties are set to their initial values. Then you should initialize *DataContext.*{*}{_}Current{_}* static property to declare *DataContext* in the current thread. Do not worry about *DataContext,* it is available in the current thread from the *DataContext.* *DataContext* static property.
If the *DataContext* goes out of scope, it will not be close. Therefore, you must explicitly close the context by calling *Dispose*.
The *DataContext.*{*}{_}Current{_}* property is a thread save. You should initialize it in all threads. By changing the *DataContext.*{*}{_}Current{_}* property you can connect to different meta model, but only one connection is active.
*Example:* The following example initializes *DataContext* in the current thread.
{newcode:c-sharp}
// Step 0. Connection String
string connectionString = "Data Source=(local);Initial Catalog=TestDatabase;User ID=sa;Password=;";
// Step 1. Initiaze Sql Metamodel
DataContext.Current = new DataContext(connectionString);
{newcode}
*Recommendation:* In ASP.NET application, we recommend to initialize DataContext in the *Global.* *{_}Application_BeginRequest{_}* method.
h4. MetaClassManager Class
The MetaClassManager represents the entry point to meta model. It is available from *DataContext.*{*}{_}MetaModel{_}* property. The MetaModel is used to get meta classes, registered meta types and relationships, create meta classes, and delete meta classes.
Also, MetaClassManager includes static events: *MetaClassCreating*, *MetaClassCreated*, *MetaClassDeleting*, *MetaClassDeleted*, *MetaFieldCreating*, *MetaFieldCreated*, *MetaFieldDeleting*, *MetaFieldDeleted*. You can subscribe to these events to get information about external meta model modifications.
h4. Metamodel Edit Scope
Business Meta Model can enter two modes. A runtime mode is default state that allows working with objects, you can create, load, updated and delete entity objects. If you change the metamodel you should activate Design mode.
| *Mode* | *Description* |
| Runtime | It is the default mode. Users can work with data only. |
| Design | Enables users to modify metamodel |
| | |
A metamodel can be modified only in Design mode. The Design Mode creates a local copy of meta model and commits modifications only after final commit.
Upon instantiating a *MetaClassManagerEditScope* by the calling *MetaClassManager.*{*}{_}BeginEdit{_}* statement, the metamodel manager determines which mode to participate in. Once determined, the scope always participates in that edit scope. You can obtain a reference to the ambient edit scope by calling the *Current* property of the *MetaClassManagerEditScope* class.
If no exception occurs within the transaction scope (that is, between the initialization of the *MetaClassManagerEditScope* object and the calling of its Dispose method), then the transaction in which the scope participates is allowed to proceed. If an exception does occur within the edit scope, the transaction in which it participates will be rolled back.
When your application completes all work it wants to perform in a transaction, you should call the *SaveChanges* method only once to inform that metamodel manager that it is acceptable to commit the transaction. Failing to call this method aborts the transaction. After, the *SaveChanges* metamodel modifications are available for all users.
A call to the *Dispose* method marks the end of the edit scope. Exceptions that occur after calling this method may not affect the transaction.
*Example:* Open metamodel edit scope
{newcode:c-sharp}
// Open Meta model edit scope
using (MetaClassManagerEditScope scope =
DataContext.Current.MetaModel.BeginEdit())
{
// TODO: Modify meta model here
// Save Changes
scope.SaveChanges();
}
{newcode}
h4. MetaType Class
MetaType represents field type declarations: string, html text, numder, enums, file, image, etc. MetaType has all popular types and extend it with UI friendly types. For example, instead of using one type of string, Business Meta Model has Short String, Long String, Html, Email, Phone number, etc. You can easily create a new MetaType based on system type or create a custom one.
Call the *RegisteredTypes* method of *MetaClassManager* class to get all registered meta types.
h5. Default Meta Types
BAF has several ready-to-use meta types:
| *Name* | *System Type* | *Description* |
| Guid | Guid | Represents a globally unique identifier (GUID). \\ |
| DateTime | DateTime | Represents an instant in time, typically expressed as a date and time of day. |
| Date | DateTime | Represents an instant in date. |
| Integer | Integer | Represents a 32-bit signed integer. |
| Float | Double | Represents a double-precision floating-point number. |
| Currency | Currency | Represents a currency number |
| CheckboxBoolean | Boolean | Represents a Boolean value with checkbox. |
| DropDownBoolean | Boolean | Represents a Boolean value with drop-down. |
| Text | String | Represents text with fixed length. Maximum length is 4096 chars. |
| EMail | String | Represent e-mail string. |
| Url | String | Represent url string. |
| LongText | String | Represent long text. |
| Html | String | Represents html string |
| File | File | Represent file (name, length, content type, stream) |
| Image | File | Represent image file |
| IntegerPercent | Integer | Represents a 32-bit signed integer percent. |
| FloatPercent | Double | Represents a double-precision floating-point percent. |
| Duration | Integer | Represents a 32-bit signed integer duration value. |
| | | |
h5. Create a New Meta Type Based on System Type
Business Foundation is designed to enable you to easily use a number of different meta types for your .NET applications. You can use the default meta types that are included with the BF, or you can implement your own meta type.
You can easily create a new meta type based on system type. Complete list of system types you can find in *McDataType* enumerators.
To create a new type, for example Geolocation based on String system type you should open edit scope and add a new *MetaFieldType* object to *MetaClassManager.*{*}{_}RegisteredTypes{_}* collection.
{newcode:c-sharp}
// Open Meta model edit scope
using (MetaClassManagerEditScope scope =
DataContext.Current.MetaModel.BeginEdit())
{
// Add a new meta type
MetaFieldType geoLocation = new MetaFieldType("Geolocation",
"Geolocation", McDataType.String);
DataContext.Current.MetaModel.RegisteredTypes.Add(geoLocation);
// Save Changes
scope.SaveChanges();
}
{newcode}
Or add a new record to mcmd_MetaFieldType table and restart application.
{newcode:c-sharp}
*INSERT INTO mcmd_MetaFieldType ([Name], [FriendlyName], [McDataType]) VALUES ('Geolocation', 'Geolocation ', 6)*
{newcode}
After registration, you can add geolocation field to meta class. Using meta type name you can load a new gelolocation view, edit UI control.
h5. Create a new meta type
BF is designed to enable you to easily use a number of different meta types for your .NET applications. You can use the default meta types that are included with the BF, or you can implement your own meta type.
When implementing a custom meta type, you are required to create Meta field installer and Meta field property binder. When you create a new meta field, BF calls meta field installer to process meta field into SQL columns. When you load entity object, BF calls meta object property binder to convert value from SQL column to meta field value.
To create a custom Meta field installer, you create a class that implements the *IMetaFieldInstaller* interface. You should implement *AssignDataSource*, *AssignValidators*, *UpdateDataSource*, *UpdateValidators*, *RemoveDataSource*, *RemoveValidators* methods.
| Name | Description |
| AssignDataSource | Create a new columns in the SQL database from meta field \\ |
| AssignValidators | Assign default validators |
| UpdateDataSource | Update SQL columns from updated meta field |
| UpdateValidators | Update validators |
| RemoveDataSource | Remove columns from SQL database |
| RemoveValidators | Remove validators |
| | |
To create a custom Meta object property binder, you create a class that implements the *IMetaObjectPropertyBinder* interface. You should implement *PostLoad*, *PostLoad*, *PreSave*, *PostSave*, *Delete*, *InitTableConfig* methods.
| Name | Description |
| PreLoad | Load value from SQL row and save to meta field property |
| PostLoad | Fill properties by other. |
| PreSave | Save value to SQL row |
| PostSave | Fill properties by other. |
| Delete | Clean up if meta field is removing |
| InitTableConfig | Initialize additional SQL relations |
| | |
Custom meta field installer and meta object property binder should be registered in the application's config file, in the *mediachase.businessFoundation.data/metaObject/types* section.
{newcode:xml}
<mediachase.businessFoundation.data>
<metaObject>
<types>
<add name="CustomType" installer="" binder="" />*
</types>
{newcode}
h4. MetaClass class
MetaClass represent class. Meta Classes consist of meta fields. Fields represent information that an object contains. Fields are like variables because they can be read or set directly. For example, if you have an object named "Car" you could store its color in a field named "Color."
You can use meta class to create entity object. You can modify meta class fields (add, remove) at runtime. MetaClass can be extended with several card, but only one card can be active in the entity object. Each card can has own field set.
*Note:* MetaClass has optional *TitleFieldName* property. The property specifies the name of title field. You should define TitleFieldName with correct string field name if want create reference to this meta class.
h5. Get collection of meta classes
The collection of table is available from *MetaClassManager.*{*}{_}MetaClasses{_}* property. It returns *MetaClassCollection* object.
*Example:* The following example writes to trace only user tables
{newcode:c-sharp}
// Step 2. Get MetaModel
MetaClassManager metaModel = DataContext.Current.MetaModel;
// Step 3. Enum Meta Classes
foreach (MetaClass mc in metaModel.MetaClasses)
{
Trace.WriteLine(mc.Name);
}
{newcode}
h5. Create meta class
Call *CreateMetaClass* method of *MetaClassManager* class, passing class name, friendly name, plural name, primary table name and primary key type to create a new meta class.
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
*Example:* Create a new meta class
{newcode:c-sharp}
// Open Meta model edit scope
using (MetaClassManagerEditScope scope =
DataContext.Current.MetaModel.BeginEdit())
{
// Create Meta Class
MetaClass newMetaClass = DataContext.Current.MetaModel.CreateMetaClass
(Name, FriendlyName, PluralName, PrimaryTable, PrimaryKeyType);
// Save Changes
scope.SaveChanges();
}
{newcode}
h5. Delete meta class
Call *DeleteMetaClass* method of *MetaClassManager* class, passing meta class object to delete meta class. The method removes a meta class definition and all data, references and permission specifications for that meta class.
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
*Example:* Find meta class by name and delete
{newcode:c-sharp}
// Open Meta model edit scope
using (MetaClassManagerEditScope scope =
DataContext.Current.MetaModel.BeginEdit())
{
// Find table
MetaClass mc = DataContext.Current.MetaModel.MetaClasses ["Class_1"];
// Drop table
DataContext.Current.MetaModel.DeleteMetaClass (table);
// Save Changes
scope.SaveChanges();
}
{newcode}
h5. Meta Class Card
MetaClass can be extended with several card, but only one card can be active in the entity object. Each card can has own field set.
For example: we created a new meta class Client, marked that meta class support cards and created three card "Regional Client", "Foreign Client" and "Partner" with own field sets. If we create a new client object without card, only meta class field are available but if we set card property, the fields from card will be available in the entity object, automatically.
!worddav678889ada2bedc2fd64800814f75bd52.png|height=495,width=569!
To allow card extension, you should create Card field in the meta class. Card field is used to save reference to the current card. Call *CreateCardField* method of *MetaClass* to create a card field. Only one card field can be added to meta class.
If meta class has card field, you can create Card meta class. Call *CreateCardMetaClass* method of *MetaClassManager* class, passing owner meta class, card name, card friendly name, card plural name, card primary table name to create a new card for specified meta class. Card meta class is visible in collection of meta classes, like original meta class, but it has *IsCard* property with true value. You can add meta field or delete card meta class as good as common meta class.
Call *CardOwner* property of MetaClass to get card owner for the current card.
Call *SupportsCards* property of *MetaClass* class to specifies whether the meta can has card.
Call *GetMetaClassSupportedCard* of *MetaClassManager* class to get collection of meta classes which support cards.
To start work with the card, you should create entity object, passing current card meta class name to the card field and all card field are available in the current entity object. When you save object it would save original common fields, current card type and current card field.
Card field are loaded automatically and available in the filter expressions.
h5. Validators
Meta class supports validation. The Validator is used to ensure that meta class is configured properly. Validators are instantiated during runtime time when you save entity object; if a meta class is not configured properly, the validator will throw exception for the incorrect values.
By default, meta fields add validators to meta class. For example email field add email validator to check that e-mail property has correct e-mail, text field add max length validator and etc.
Call *Validators* property of *MetaClass* class to get collection of validators in the current class.
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
You can create and add custom validator. To create a custom validator, you should create a class that implements the *IValidator*. You should implement *ErrorMessage* and *IsValid* properties and *Validate* method. Then you can add validator to collection of validators in the current class.
*Note:* If you develop custom meta type, you should add your validators in AssignValidators and remove in RemoveValidators methods of meta field installer.
*Example:* CurrencyFieldValidator
{newcode:c-sharp}
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Globalization;
namespace Mediachase.BusinessFoundation.Data
{
/// <summary>
/// Represents currency field validator.
/// </summary>
public class CurrencyFieldValidator : BaseFieldValidator
{
private bool _allowNull = true;
public CurrencyFieldValidator()
{
}
public bool AllowNull
{
get { return _allowNull; }
set { _allowNull = value; }
}
protected override bool EvaluateIsValid()
{
object fieldValue = base.GetValue();
// Check Null
if (fieldValue == null && !this.AllowNull)
{
base.ErrorMessage = string.Format(CultureInfo.InvariantCulture, "The '{0}' field doesn't allow null.", this.FieldName);
return false;
}
if (fieldValue == null)
return true;
// Check Type
if (fieldValue.GetType() != typeof(Decimal))
{
base.ErrorMessage = string.Format(CultureInfo.InvariantCulture, "Wrong type '{1}'. '{0}' field expects decimal.", this.FieldName, fieldValue.GetType().GetType());
return false;
}
return true;
}
}
}
{newcode}
h4. MetaField class
A *MetaField* object represent a meta class field. Fields represent information that an object contains. Fields are like variables because they can be read or set directly. For example, if you have an object named "Car" you could store its color in a field named "Color."
From *MetaField* object you can get complete information about field:
* Name
* Meta Type
* Default Value
* Formula for auto-calculated columns
* Is Nullable
* Is ReadOnly
* Is Primary Key
h5. Get collection of meta fields
The collection of meta fields is available from *MetaClass.*{*}{_}Fields{_}* property. It returns *MetaFieldCollection* object.
*Example:* The following example writes all fields to trace
{newcode:c-sharp}
foreach (MetaField field in mc.Fields)
{
System.Diagnostics.Trace.WriteLine(field.Name);
{newcode}
h5. Add meta field
Call *CreateMetaField* method of *MetaClass* class, passing name, friendly name, type, is nullable flag, default value and attributes to create a new meta field. Attributes are depended on meta type.
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
*Example:* Create a new Guid meta field
{newcode:c-sharp}
public MetaField CreateGuid(string name, string friendlyName, bool isNullable)
{
if (name == null)
throw new ArgumentNullException("name");
if (friendlyName == null)
throw new ArgumentNullException("friendlyName");
AttributeCollection attr = new AttributeCollection();
string defaultValue = isNullable ? string.Empty : "newid()";
MetaField retVal = this.MetaClass.CreateMetaField(name, friendlyName, MetaFieldType.Guid, isNullable, defaultValue, attr);
return retVal;
}
{newcode}
*Note:* BF uses meta field installer assigned with meta type to add meta field to meta class.
h5. Delete meta field
Call *DeleteMetaField* method of *MetaClass* class, passing meta field object to delete field from meta clas.
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
*Example:* Find column by name and drop
{newcode:c-sharp}
// Step 5. Delete field
mc. DeleteMetaField(mc.Fields\["Book Title"]);
{newcode}
*Note:* BF uses meta field installer assigned with meta type to add meta field to meta class.
h4. MetaFieldBuilder class
To improve creation meta field based on system meta type, BF has MetaFieldBuilder class. You can use it to create meta field based on system meta type.
The methods are available in MetaFieldBuilder class:
* CreateGuid
* CreateDateTime
* CreateDate
* CreateInteger
* CreateFloat
* CreateCurrency
* CreateCheckBoxBoolean
* CreateDropDownBoolean
* CreateText
* CreateEmail
* CreateUrl
* CreateLongText
* CreateHtml
* CreateFile
* CreateImage
* CreateReference
* CreateReferencedField
* CreateBackReference
* CreateCardField
* CreateEnumField
* CreateAggregation
* CreateIntegerPercent
* CreateFloatPercent
* CreateDecimalPercent
* CreateDecimal
* CreateDuration
*Note:* MetaFieldBuilder opens Edit scope automatically.
*Example:* Suing MetaFieldBuilder to create meta field
{newcode:c-sharp}
using (MetaFieldBuilder builder = new MetaFieldBuilder(metaClass))
{
builder.CreateDateTime(CreatedFieldName, CreatedFriendlyName, false, true);
builder.CreateText(CreatorFieldNameText, CreatorFriendlyName, false, 50, false);
builder.CreateGuid(CreatorFieldNameGuid, CreatorFriendlyName, false);
builder.CreateInteger(CreatorFieldNameInteger, CreatorFriendlyName, false, -1);
builder.SaveChanges();
}
{newcode}
h4. MetaEnum class
MetaEnum represents enumeration. Enumeration can be single or multi select. When a new meta enum is created, new meta type with *McDataType* property with *McDataType.Enum* value is registered.
If enumerator has been created, you can create a new field with enumerator meta type.
The entity object property returns selected item id (Int32) or array of selected item id (Int32\[\]).
h5. Get collection of enumerators
Because enumerator is original meta type, you can get all enumerators from *MetaClassManager.*{*}{_}RegisteredTypes{_}* property.
*Example:* Find all enumerators
{newcode:c-sharp}
foreach(MetaFieldType type in DataContext.Current.MetaModel.RegisteredTypes)
{
if (type.McDataType == McDataType.Enum)
{
// We have found enumerator
}
}
{newcode}
h5. Create a new enumerator
Call *Create* method of *MetaEnum* class, passing type name, friendly name and multy value flag to create a new enumerator.
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
*Example:* Create a new enumerator
{newcode:c-sharp}
MetaFieldType newEnum = MetaEnum.Create(enumName, enumFriendlyName, bMultiValue);
{newcode}
h5. Manage enumerator
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
Call *IsUsed* method of *MetaEnum* class, passing meta type to determine if enumerator is using in any meta class.
Call *AddItem* method of *MetaEnum* class, passing meta type, item friendly name and order id to add enum item to enumerator.
Call *RemoveItem* method of *MetaEnum* class, passing meta type and item id to remove enum item.
Call *GetItems* method of *MetaEnum* class, passing meta type to get all enum items.
Call *UpdateItem* method of *MetaEnum* class, passing meta type, item friendly name and order id to update enum item.
Call *RenameItem* method of *MetaEnum* class, passing meta type, item id and new enum name to rename enum item.
Call *ChangeOrder* method of *MetaEnum* class, passing meta type, item id and new order id to rename enum item.
h5. Create an enum meta field
If enumerator has been created, you can create a new field with enumerator meta type.
*Note:* A meta model can be modified in only Design mode. You should open edit scope.
*Example:* Creation of enum meta field
{newcode:c-sharp}
public MetaField CreateEnumField(string name, string friendlyName, string enumName, bool isNullable, string defaultValue, bool enumEditable)
{
if (name == null)
throw new ArgumentNullException("name");
if (friendlyName == null)
throw new ArgumentNullException("friendlyName");
AttributeCollection attr = new AttributeCollection();
attr.Add(McDataTypeAttribute.EnumEditable, enumEditable);
MetaField retVal = this.MetaClass.CreateMetaField(name, friendlyName, enumName, isNullable, defaultValue, attr);
return retVal;
}
{newcode}
h5. Remove Enumerator
Call *Remove* method of *MetaEnum* class, passing meta type to delete enumerator.
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
h4. References
BF supports 1-N, N-N and aggregation references between two meta classes.
h5. 1-N Reference
BF supports 1-N reference between two meta classes.
*Note:* You should define *TitleFieldName* property of *MetaClass* class with correct string field name if want to create reference to this meta class.
Call *CreateReference* method of *MetaClass* class, passing parent meta class, reference name, frianldy name and is nullable flag to create reference to parent meta class.
The code below show how to create reference between Project and Task.
{newcode:c-sharp}
// Open Meta model edit scope
using (MetaClassManagerEditScope scope = DataContext.Current.MetaModel.BeginEdit())
{
// Create reference
DataContext.Current.GetMetaClass("Task").CreateReference(
DataContext.Current.GetMetaClass("Project"), "Project", "Project", true)):
// Save Changes
scope.SaveChanges();
}
{newcode}
!worddav799089f690a2f016ea1c6e04e06d63b5.png|height=272,width=559!
The *CreateReference* method adds two fields to the meta class:
* Reference Id -- It is reference on parent primary key. Named "*_\[ReferenceName\]_{*}{*}Id*".
* Reference Title -- It's read-only referenced field property to parent title. Named "*_\[ReferenceName\]_*".
Reference Id field is used to get, set reference to the parent object. Reference Title is used to get title of parent object. When you update Reference Id, Reference Title would be updated automatically.
*Note:* You can create many references between two meta classes.
h5. Referenced field
After reference creation, you can add any field from parent meta class as Reference field. All referenced fields are read-only. If reference not set, reference field returns null. When you update Reference Id, all referenced field would be updated automatically.
!worddav6db0659037c1dfe1461f36ca71d50680.png|height=273,width=559!
Call *CreateReferencedField* method of *MetaClass* class, passing reference field to parent meta class, parent field and field name to add referenced field to meta class.
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
h5. Back Reference
After reference creation, in the parent meta class, you can create back reference field on existing reference. The back reference field returns collection of child object that have reference to the current object.
Call *CreateBackReference* method of *MetaClass* class, passing reference field and field name to add back references field.
*Note:* A metamodel can be modified in only Design mode. You should open edit scope.
!worddav275b3a09538f0a3276217aa027254cc4.png|height=382,width=557!
h5. N-N Reference. Code name Bridge
BF supports N-N reference between two meta classes. The bridge is meta class with two reference on class #1 and class #2.
*Note:* You should define *TitleFieldName* property of *MetaClass* class in both meta classes.
Call *CreateBridge* method of *MetaClassManager* class, passing class #1 and class #2 to create a bridge between two meta classes. Bridge meta class is visible in collection of meta classes, like original meta class, but it has *IsBridge* property with true value. You can add meta field or delete bridge meta class as good as common meta class.
The diagram below shows bridge between two meta classes Project and Union.
!worddav3a1154c8213747bab118cfd273f4fb42.png|height=380,width=559!
h5. Aggregation
BF supports aggregation reference between two meta classes.
*Note:* You should define *TitleFieldName* property of *MetaClass* class with correct string field name if want to create a aggregation in this class.
Aggregation is slightly more complex than reference. You typically use it to enable the parent entity object has collection of child entity object, where one element is marked is default. The default children entity object is loaded when parent object is loaded and available from the property. The properties of children entity object can be modified and would be saved when you save parent object. When you delete parent object, all aggregated objects is removed automatically.
Call *CreateAggregation* method of *MetaClass* class, passing children meta class to add aggregation to meta class. The method adds a new meta field to parent meta class. You can use it set, update aggregated object.
{newcode:c-sharp}
public MetaField CreateAggregation(string name, string friendlyName, string childMetaClassName,string elementContainerRefFieldFriendlyName,string defaultElementFieldFriendlyName)
{
MetaField retVal = this.MetaClass.CreateAggregation(childMetaClassName, name, friendlyName,
elementContainerRefFieldFriendlyName,
defaultElementFieldFriendlyName);
return retVal;
}
{newcode}
*Note:* A meta model can be modified in only Design mode. You should open edit scope.
The diagram below shows Client and Address meta classes. Client meta class aggregates Address meta class. The client has many addresses but one is marked as default and available from Cleint.Address property. The Address property returns entity object and you can updated default address properties as client properties. When you save client, default address is saved automatically.
!worddav410b73f952befd87ff79809224497287.png|height=271,width=558!