Example E269
Visible to All Users

How to persist metadata

Files to look at:

This example shows how to dynamically create persistent classes and properties, and to reuse XPO to store this information. The example is of a high level of complexity. Only advanced users may be interested in it, if they create a framework with XPO and allow their end-users to create or customize data objects and properties.

See Also:
How to define a persistent class at runtime

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

MetadataObjects.cs(vb)
C#
using System; using System.Collections.Generic; using System.Text; using DevExpress.Xpo; using DevExpress.Xpo.Metadata; namespace PersistentMetadata { [NonPersistent] public class MyBaseObject : XPObject { public MyBaseObject(Session session, XPClassInfo classInfo) : base(session, classInfo) { } } public abstract class PersistentTypeInfo : XPObject { public PersistentTypeInfo(Session session) : base(session) { } string _Name; public string Name { get { return _Name; } set { SetPropertyValue("Name", ref _Name, value); } } [Association] public XPCollection<PersistentAttributeInfo> TypeAttributes { get { return GetCollection<PersistentAttributeInfo>("TypeAttributes"); } } protected void CreateAttributes(XPTypeInfo ti) { foreach(PersistentAttributeInfo a in TypeAttributes) { ti.AddAttribute(a.Create()); } } } public class PersistentClassInfo : PersistentTypeInfo { public static void FillDictionary(XPDictionary dictionary, ICollection<PersistentClassInfo> data) { foreach(PersistentClassInfo twc in data) { twc.CreateClass(dictionary); } foreach(PersistentClassInfo twc in data) { twc.CreateMembers(dictionary); } } public const string AssemblyName = ""; public PersistentClassInfo(Session session) : base(session) { } protected virtual Type GetDefaultBaseClass() { return typeof(MyBaseObject); } public XPClassInfo CreateClass(XPDictionary dictionary) { XPClassInfo result = dictionary.QueryClassInfo(AssemblyName, Name); if(result == null) { XPClassInfo baseClassInfo; if(BaseClass != null) baseClassInfo = BaseClass.CreateClass(dictionary); else baseClassInfo = dictionary.GetClassInfo(GetDefaultBaseClass()); result = dictionary.CreateClass(baseClassInfo, Name); CreateAttributes(result); } return result; } void CreateMembers(XPDictionary dictionary) { XPClassInfo ci = dictionary.GetClassInfo(AssemblyName, Name); foreach(PersistentMemberInfo mi in OwnMembers) { mi.CreateMember(ci); } } PersistentClassInfo _BaseClass; public PersistentClassInfo BaseClass { get { return _BaseClass; } set { SetPropertyValue("BaseClass", ref _BaseClass, value); } } [Association] public XPCollection<PersistentMemberInfo> OwnMembers { get { return GetCollection<PersistentMemberInfo>("OwnMembers"); } } } public abstract class PersistentMemberInfo : PersistentTypeInfo { public PersistentMemberInfo(Session session) : base(session) { } internal XPMemberInfo CreateMember(XPClassInfo owner) { XPMemberInfo result = owner.FindMember(Name); if(result == null) result = CreateMemberCore(owner); CreateAttributes(result); return result; } protected abstract XPMemberInfo CreateMemberCore(XPClassInfo owner); PersistentClassInfo _Owner; [Association] public PersistentClassInfo Owner { get { return _Owner; } set { SetPropertyValue("Owner", ref _Owner, value); } } } public class PersistentReferenceMemberInfo : PersistentMemberInfo { public PersistentReferenceMemberInfo(Session session) : base(session) { } PersistentClassInfo _ReferenceType; public PersistentClassInfo ReferenceType { get { return _ReferenceType; } set { SetPropertyValue("ReferenceType", ref _ReferenceType, value); } } protected override XPMemberInfo CreateMemberCore(XPClassInfo owner) { XPMemberInfo member = owner.CreateMember(Name, ReferenceType.CreateClass(owner.Dictionary)); return member; } } public class PersistentCollectionMemberInfo : PersistentMemberInfo { public PersistentCollectionMemberInfo(Session session) : base(session) { } protected override XPMemberInfo CreateMemberCore(XPClassInfo owner) { return owner.CreateMember(Name, typeof(XPCollection), true); } } public class PersistentCoreTypeMemberInfo : PersistentMemberInfo { public PersistentCoreTypeMemberInfo(Session session) : base(session) { } string _TypeName; public string TypeName { get { return _TypeName; } set { SetPropertyValue("TypeName", ref _TypeName, value); } } protected override XPMemberInfo CreateMemberCore(XPClassInfo owner) { return owner.CreateMember(Name, Type.GetType(TypeName, true)); } } public abstract class PersistentAttributeInfo : XPObject { public PersistentAttributeInfo(Session session) : base(session) { } public abstract Attribute Create(); PersistentTypeInfo _Owner; [Association] public PersistentTypeInfo Owner { get { return _Owner; } set { SetPropertyValue("Owner", ref _Owner, value); } } } public class PersistentAssociationAttribute : PersistentAttributeInfo { public PersistentAssociationAttribute(Session session) : base(session) { } string _an; public string AssociationName { get { return _an; } set { SetPropertyValue("AssociationName", ref _an, value); } } string _ean; public string ElementAssemblyName { get { return _ean; } set { SetPropertyValue("ElementAssemblyName", ref _ean, value); } } string _etn; public string ElementTypeName { get { return _etn; } set { SetPropertyValue("ElementTypeName", ref _etn, value); } } public override Attribute Create() { return new AssociationAttribute(AssociationName, ElementAssemblyName, ElementTypeName); } } }
Program.cs(vb)
C#
using System; using System.Collections.Generic; using System.Text; using System.IO; using DevExpress.Xpo; using DevExpress.Xpo.Metadata; using DevExpress.Xpo.DB; using System.Collections; namespace PersistentMetadata { class Program { static void Main(string[] args) { new PersistentMetadataExample().Execute(); } } public class PersistentMetadataExample { public void Execute() { InitDataLayers(); CreateMetadata(); CreateDatabaseAndDefaultData(); LoadData(); } IDataLayer metadataStorage, dataStorage; void InitDataLayers() { string metadataFileName = "Metadata.xml"; string dataFileName = "Data.mdb"; if(File.Exists(metadataFileName)) File.Delete(metadataFileName); if(File.Exists(dataFileName)) File.Delete(dataFileName); metadataStorage = XpoDefault.GetDataLayer(InMemoryDataStore.GetConnectionString(metadataFileName), AutoCreateOption.DatabaseAndSchema); dataStorage = XpoDefault.GetDataLayer(AccessConnectionProvider.GetConnectionString(dataFileName), AutoCreateOption.DatabaseAndSchema); } void CreateMetadata() { using(UnitOfWork uof = new UnitOfWork(metadataStorage)) { PersistentClassInfo classCustomer = new PersistentClassInfo(uof); classCustomer.Name = "Customer"; PersistentCoreTypeMemberInfo propFullName = new PersistentCoreTypeMemberInfo(uof); propFullName.Name = "FullName"; propFullName.TypeName = typeof(string).FullName; classCustomer.OwnMembers.Add(propFullName); PersistentCollectionMemberInfo propOrders = new PersistentCollectionMemberInfo(uof); propOrders.Name = "Orders"; classCustomer.OwnMembers.Add(propOrders); PersistentAssociationAttribute attrCustomerOrders = new PersistentAssociationAttribute(uof); attrCustomerOrders.ElementTypeName = "Order"; propOrders.TypeAttributes.Add(attrCustomerOrders); PersistentClassInfo classOrder = new PersistentClassInfo(uof); classOrder.Name = "Order"; PersistentCoreTypeMemberInfo propOrderDate = new PersistentCoreTypeMemberInfo(uof); propOrderDate.Name = "OrderDate"; propOrderDate.TypeName = typeof(DateTime).FullName; classOrder.OwnMembers.Add(propOrderDate); PersistentReferenceMemberInfo propCustomer = new PersistentReferenceMemberInfo(uof); propCustomer.Name = "Customer"; propCustomer.ReferenceType = classCustomer; classOrder.OwnMembers.Add(propCustomer); PersistentAssociationAttribute attrOrdersCustomer = new PersistentAssociationAttribute(uof); propCustomer.TypeAttributes.Add(attrOrdersCustomer); uof.CommitChanges(); } } void InitDataDictionary(UnitOfWork dataSession) { using(UnitOfWork metadataSession = new UnitOfWork(metadataStorage)) { XPCollection<PersistentClassInfo> classes = new XPCollection<PersistentClassInfo>(metadataSession); PersistentClassInfo.FillDictionary(dataSession.Dictionary, classes); } } readonly int OrderCount = 1; readonly DateTime OrderDate = DateTime.Today; void CreateDatabaseAndDefaultData() { using(UnitOfWork dataSession = new UnitOfWork(dataStorage)) { InitDataDictionary(dataSession); dataSession.UpdateSchema(dataSession.GetClassInfo(null, "Customer"), dataSession.GetClassInfo(null, "Order")); XPClassInfo classCustomer = dataSession.GetClassInfo("", "Customer"); XPBaseObject customer = (XPBaseObject)classCustomer.CreateNewObject(dataSession); customer.SetMemberValue("FullName", "John Doe"); for(int i = 0; i < OrderCount; i++) { XPClassInfo classOrder = dataSession.GetClassInfo("", "Order"); XPBaseObject order = (XPBaseObject)classOrder.CreateNewObject(dataSession); order.SetMemberValue("OrderDate", OrderDate); order.SetMemberValue("Customer", customer); } dataSession.CommitChanges(); } } void LoadData() { using(UnitOfWork dataSession = new UnitOfWork(dataStorage)) { InitDataDictionary(dataSession); XPClassInfo classCustomer = dataSession.GetClassInfo("", "Customer"); XPBaseObject customer = (XPBaseObject)dataSession.FindObject(classCustomer, null); IList orders = (IList)customer.GetMemberValue("Orders"); } } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.