ExternalId changes when database is evolved
CapableObjects Forums
Home       Members    Calendar    Who's On
Welcome Guest ( Login | Register )
        



ExternalId changes when database is evolved Expand / Collapse
Author
Message
Posted 2010-05-11 11:09:30
Forum Member

Forum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum Member

Group: Forum Members
Last Login: 2011-12-22 17:31:00
Posts: 34, Visits: 620
When a DB is evolved, the prefix of external ids changes, e.g. from 121!G!313dc40f-f21a-4c59-a541-0ae1088b572b to 122!G!313dc40f-f21a-4c59-a541-0ae1088b572b

I use external ids in the query string of some of my asp.net pages and in personalisation data for web parts, this means that shortcuts etc break when the database is evolved.

Is it possible to change this behaviour?
Post #5203
Posted 2010-05-11 12:31:08
Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

Group: Forum Members
Last Login: 2011-07-14 17:05:00
Posts: 290, Visits: 2 617
ExternalID is a session specific ID which should not be exposed. You should have an auto-inc on your class and have urls like this

ShowArticle.aspx?id=2



====
Pete
Post #5204
Posted 2010-05-11 15:51:05
Forum Member

Forum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum Member

Group: Forum Members
Last Login: 2011-12-22 17:31:00
Posts: 34, Visits: 620
Peter Morris (2010-05-11)
ExternalID is a session specific ID which should not be exposed. You should have an auto-inc on your class and have urls like this

ShowArticle.aspx?id=2



I use GUIDs as IDs to avoid having to do that. Changing my project to use auto-incs is not practical.

The external ID is not session specific unless it refers to a transient or new object.
Post #5206
Posted 2010-05-12 00:13:14
Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

Group: Forum Members
Last Login: 2011-11-18 23:48:32
Posts: 139, Visits: 410
Search for thread "Best way to expose externalId for binding".  It has a lengthy discussion on this topic.  It started in Jan 2009.

There is a way to use GUIDs for the class type part of the external id as well.  I posted a replacement external id generator that I have been using.  I have updated the BkpExternalIdServiceImpl since the post back in Jan 2009.  Just in case someone is interested in the latest version, here is the source.

using System;
using System.Collections.Generic;
using System.Text;
using Eco.Services.Impl;
using Eco.Framework;
using Eco.Cache;
using Eco.UmlRt;
using Eco.ObjectRepresentation;
using Eco.Services;
using Eco.DataRepresentation;
using Eco.Handles;

namespace Vco.EcoUtils
{
    /// <summary>
    /// Replacement class for the ExternalIdService used by an EcoSpace. 
    /// This class will use a 22 character base64 string for the class id
    /// part of the external id.  Here is an example of an ExternalId:
    /// qFMNqVavU-iVw1cY2lp_9A!1234
    /// The normal base64 encoding '+/' characters are replaced with
    /// '-_' characters to make the external id url friendly.
    /// </summary>
    public class BkpExternalIdServiceImpl: ExternalIdServiceBase
    {
        private static object lockObject = new Object();
       
        private class EcoSpaceLookupTable
        {
            public readonly Dictionary<string, int> classIdIndexes = new Dictionary<string, int>();
            public readonly Dictionary<IClass, string> classIds = new Dictionary<IClass, string>();
        }

        private static Dictionary<IEcoTypeSystem, EcoSpaceLookupTable> ecoSpaceLookupTables = new Dictionary<IEcoTypeSystem, EcoSpaceLookupTable>();
       
        public static void RegisterTypeSystem(IEcoTypeSystem typeSystem)
        {
            lock ( lockObject ) {
                EcoSpaceLookupTable classIdLookupTable = new EcoSpaceLookupTable();
                foreach ( IClass c in typeSystem.AllClasses ) {
                    if ( !string.IsNullOrEmpty(c.Id) ) {
                        string classId = CompressGuidString(c.Id);
                        classIdLookupTable.classIds.Add(c, classId);
                        classIdLookupTable.classIdIndexes[classId] = c.InternalIndex;
                    }
                }
                ecoSpaceLookupTables.Add(typeSystem, classIdLookupTable);
            }
        }       

        private readonly Dictionary<string, int> classIdIndexes;
        private readonly Dictionary<IClass, string> classIds;

        public BkpExternalIdServiceImpl(IEcoTypeSystem typeSystem): base(typeSystem)
        {
            EcoSpaceLookupTable ecoSpaceLookupTable;
            lock ( lockObject ) {
                if ( !ecoSpaceLookupTables.TryGetValue(typeSystem, out ecoSpaceLookupTable) ) {
                    throw new InvalidOperationException("BkpExternalIdServiceImpl.RegisterTypeSystem was not called for TypeSystem: " + typeSystem.GetType().Name);
                }
            }
            classIdIndexes = ecoSpaceLookupTable.classIdIndexes;
            classIds = ecoSpaceLookupTable.classIds;
        }

        protected override string GetExternalClassId(IObject obj, Locator loc, ObjectId id)
        {
            string externalClassId;
            if ( !classIds.TryGetValue(obj.UmlClass, out externalClassId) ) {
                throw new InvalidOperationException(HandlesStringRes.sClassHasNoModelId(obj.UmlClass.Name));
            }
            return externalClassId;
        }

        protected override int GetTopSortedIndex(string externalClassId)
        {
            int index;
            if ( !classIdIndexes.TryGetValue(externalClassId, out index) ) {
                throw new ArgumentException(HandlesStringRes.sInvalidClassId(externalClassId));
            }
            return index;
        }
       
        /// <summary>
        /// Compresses a Guid to a 22 character base64 string.  If there is a problem making a Guid, it will revert to
        /// removing '-', '{', and '}' from the string.
        /// </summary>
        /// <param name="guidString">A Guid string in a standard format that new Guid(guidString) would take.</string></param>
        /// <returns>22 character compressed Guid</returns>
        public static string CompressGuidString(string guidString)
        {
            try {
                Guid guid = new Guid(guidString);
                return Convert.ToBase64String(guid.ToByteArray()).Substring(0, 22).Replace('+','-').Replace('/','_');
            } catch {
                StringBuilder sb = new StringBuilder(32);
                int length = guidString.Length;
                for ( int i = 0; i < length; i++ ) {
                    char ch = guidString[i];
                    if ( (ch != '-') && (ch != '{') && (ch != '}') ) {
                        sb.Append(guidString[i]);
                    }
                }
                return sb.ToString();
            }
        }

        /// <summary>
        /// Gets a list of all the external class id's.  Primary use is for debugging.
        /// </summary>
        /// <returns>A list of external class id's to use as a reference</returns>
        public string GetClassIdList()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("External Class Id's:");
            foreach ( IClass c in TypeSystem.AllClasses ) {
                if ( !string.IsNullOrEmpty(c.Id) ) {
                    sb.Append(c.Name.PadRight(40));
                    sb.AppendLine(CompressGuidString(c.Id));
                }
            }
            return sb.ToString();
        }
       

        /// <summary>
        /// Returns the ExternalClassId for an ECO class.  Primarily for use in the debugger to determine external ids on the fly.
        /// </summary>
        /// <param name="className">The class name to get the ExternalClassId from</param>
        /// <returns>The ExternalClassId</returns>
        public string GetClassId(string className)
        {
            IClass iClass = TypeSystem.AllClasses.GetItemByName(className);
            return GetClassId(iClass);
        }
   
        /// <summary>
        /// Returns the ExternalClassId for an ECO class.
        /// </summary>
        /// <param name="iClass">IClass to get the ExternalClassId from</param>
        /// <returns>The ExternalClassId</returns>
        public static string GetClassId(IClass iClass)
        {
            if ( iClass != null ) {
                return CompressGuidString(iClass.Id);
            }
            return "";
        }
       
    }

}

Post #5209
Posted 2010-05-12 13:26:31
Forum Member

Forum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum Member

Group: Forum Members
Last Login: 2011-12-22 17:31:00
Posts: 34, Visits: 620
Thanks Brian, that was a great help.

I've decided to use ExternalIdServiceImpl_DbType as the type discriminator only changes if the database is completely regenerated.

In my ecospace class I added the following method

protected override Eco.Services.Impl.ExternalIdServiceBase CreateExternalIdService(Eco.UmlRt.IEcoTypeSystem typeSystem)
{
return new Eco.Services.Impl.ExternalIdServiceImpl_DbType(typeSystem,
(MyPMP.Instance.PersistenceMapper as Eco.Persistence.AbstractPersistenceMapperDb).EffectiveRunTimeMappingProvider);
}
Post #5210
Posted 2010-05-13 10:57:13
Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

Group: Forum Members
Last Login: 2011-07-14 17:05:00
Posts: 290, Visits: 2 617
David Fowler (2010-05-11)

I use GUIDs as IDs to avoid having to do that. Changing my project to use auto-incs is not practical.
The external ID is not session specific unless it refers to a transient or new object.


By session specific I don't mean it changes per session, I mean it is not guaranteed to be the same across two sessions because the session may have been terminated due to you updating the website with a new model - at which point the externalID could easily have changed.


====
Pete
Post #5213
« Prev Topic | Next Topic »


Reading This Topic Expand / Collapse
Active Users: 0 (0 guests, 0 members, 0 anonymous members)
No members currently viewing this topic.
Forum Moderators: HansKarlsen, Jonas Hogstrom, PeterMorris

Permissions Expand / Collapse

All times are GMT +1:00, Time now is 10:12

Powered By InstantForum.NET v4.1.4 © 2012
Execution: 0,234. 9 queries. Compression Disabled.