New Posts New Posts RSS Feed: Where can I find document for how to implement the GenerateID() interface?
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Where can I find document for how to implement the GenerateID() interface?

 Post Reply Post Reply
Author
Suah View Drop Down
Newbie
Newbie
Avatar

Joined: 06-Jul-2009
Posts: 16
Post Options Post Options   Quote Suah Quote  Post ReplyReply Direct Link To This Post Topic: Where can I find document for how to implement the GenerateID() interface?
    Posted: 20-Aug-2009 at 9:52pm
Where can I find document for how to implement the GenerateID() interface?
Back to Top
GregD View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 374
Post Options Post Options   Quote GregD Quote  Post ReplyReply Direct Link To This Post Posted: 24-Aug-2009 at 4:13pm
There are a couple of mentions of IIDGenerator in the Developer Guide, which describe at a high level what it does. Other than that, there is a sample implementation (NumericIDGenerator) included in the C:\Program Files\IdeaBlade DevForce\Samples.
Back to Top
dpollot44 View Drop Down
Newbie
Newbie
Avatar

Joined: 13-Jan-2010
Location: Rochester NY
Posts: 24
Post Options Post Options   Quote dpollot44 Quote  Post ReplyReply Direct Link To This Post Posted: 13-Jan-2010 at 8:52am
I'm evaluating the software (universal) and that directory does not exist for me.  There are three sub-folders; Documentation, Learning Resources, and SilverLight Assemblies... I would have thought perhaps either of the first two might contain the sample implementations but nope.

Is the code posted somewhere (saving me the time of re-downloading/registering)
Back to Top
GregD View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 374
Post Options Post Options   Quote GregD Quote  Post ReplyReply Direct Link To This Post Posted: 13-Jan-2010 at 11:19am
Between August and now, the Learning Resources were reorganized and the sample implementation of IidGenerator was moved to the following location:

     LearningResources\040_BusObjPersistence\AddingDeleting\Snippets\NumericIdGenerator


Back to Top
dpollot44 View Drop Down
Newbie
Newbie
Avatar

Joined: 13-Jan-2010
Location: Rochester NY
Posts: 24
Post Options Post Options   Quote dpollot44 Quote  Post ReplyReply Direct Link To This Post Posted: 13-Jan-2010 at 12:14pm
I forgot to mention that the "LearningResources" folder is empty for me (I had tried to do a quick search for the .cs file and it would have found it there otherwise).  Do I just need to re-download and extract?  Perhaps a different version?
Back to Top
dpollot44 View Drop Down
Newbie
Newbie
Avatar

Joined: 13-Jan-2010
Location: Rochester NY
Posts: 24
Post Options Post Options   Quote dpollot44 Quote  Post ReplyReply Direct Link To This Post Posted: 13-Jan-2010 at 12:35pm
I reinstalled.  The full/vs. custom install didn't include the learning units.
Back to Top
dpollot44 View Drop Down
Newbie
Newbie
Avatar

Joined: 13-Jan-2010
Location: Rochester NY
Posts: 24
Post Options Post Options   Quote dpollot44 Quote  Post ReplyReply Direct Link To This Post Posted: 13-Jan-2010 at 1:00pm
...And I spoke too soon.  I've reinstalled a couple of times and the learning folder is empty each time.  Can someone just post the sample code (specifically looking for NumericIdGenerator).

Back to Top
davidklitzke View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 14-Jun-2007
Posts: 715
Post Options Post Options   Quote davidklitzke Quote  Post ReplyReply Direct Link To This Post Posted: 13-Jan-2010 at 2:26pm

I have seen some rare cases where the Learning Resources get installed to C:\MyTutorials or D:\MyTutorials (or some other drive:\MyTutorials).  I think if you look hard enough, you can find the Learning Resources.  It is extremely rare for the Learning Resources not to get installed somewhere on your hard drive.

Back to Top
GregD View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 374
Post Options Post Options   Quote GregD Quote  Post ReplyReply Direct Link To This Post Posted: 13-Jan-2010 at 5:18pm
/* A sample IIdGenerator implementation.
 *
 *  You can use this as-is (almost) or modify as needed.  This is provided as a sample only.
 *
 *  You may want to use an IIdGenerator to generate both temporary and real Id values for
 *  key fields of your Entities.  Note that for tables using keys based on identity or sequence/serial
 *  values the StoreGeneratedIdGenerator provided by the DevForce framework should be sufficient.
 *
 *  Possible customizations -
 *     - change the namespace
 *     - change the class name
 *     - alter IsApplicable() logic for your data source key
 *     - alter GetNextTempId() logic for custom temporary Id values
 *     - alter GetReadIdMap() logic for custom real Id allocation
 *     
 *  Place your IdGenerator class in an assembly which can be deployed on both client and server.
 *
 *  If you implement a custom IIdGenerator, place the assembly name in either the
 *  ProbeAssemblyNames for a given data source key or the ProbeAssemblyNames
 *  at the root of the IdeaBlade Configuration file.  
 *
*/
using System;
using System.Data;
using System.Runtime.Serialization;

using IdeaBlade.Ado;
using IdeaBlade.Core;
using IdeaBlade.EntityModel;

namespace IdeaBladeTest1Model {

  /// <summary>
  /// Sample IIdGenerator implementation.  The class should be marked with the Serializable
  /// or DataContract attribute if you plan to save and restore the EntityCache to/from files.
  /// </summary>
  [DataContract]
  public class NumericIdGenerator : IIdGenerator {

    /// <summary>
    /// An instance of the IIdGenerator will be instantiated by the DevForce framework
    /// on both the client and server.  A public parameterless constructor is required.
    /// </summary>
    public NumericIdGenerator() {
    }

    /// <summary>
    /// Return true if this IIdGenerator should be used with the specified key.
    /// </summary>
    /// <remarks>
    /// In this example we test the key name, but this is for illustration only.  Be sure to
    /// change this code for your implementation.  If you require an IdGenerator but DevForce
    /// can't find an "applicable" one, an exception is thrown.  Called on both client and server.
    /// </remarks>
    public bool IsApplicable(IDataSourceKey dataSourceKey) {
      return dataSourceKey.Name.StartsWith("IdeaBladeTest1");
    }

    /// <summary>
    /// Called by DevForce on the client to retrieve a temporary Id value for the specified column.
    /// </summary>
    /// <remarks>
    /// This example returns negative values starting at -1.  If you need custom temporary Ids then
    /// change this logic as necessary.
    /// Be sure to store all temporary Ids.  The framework will request them in the <see cref="TempIds"/>
    /// property.
    /// </remarks>
    public object GetNextTempId(DataEntityProperty entityColumn) {
      Object id;
      _nextBaseId++;
      long longId = (long) (-1 * _nextBaseId);
      try {
        id = Convert.ChangeType(longId, entityColumn.DataType);
      } catch {
        throw new NotSupportedException("This id generator cannot generate ids of type " + entityColumn.DataType);
      }

      _tempIds.Add(new UniqueId(entityColumn, id));
      return id;
    }  

    /// <summary>
    /// Called by DevForce on the client to retrieve a collection of the temporary Id values generated since
    /// the last <see cref="Reset"/> call.  
    /// </summary>
    /// <remarks>
    /// Be sure to maintain the collection of temporary Ids generated in <see cref="GetNextTempId"/>.
    /// </remarks>
    public UniqueIdCollection TempIds {
     get { return _tempIds; }
    }

    /// <summary>
    /// Return whether the specified Id is a temporary Id generated by this IdGenerator.
    /// </summary>
    /// <remarks>
    /// DevForce will call this on the client to test whether the specified Id is temporary and will require
    /// "fixup" as a real id.  
    /// </remarks>
    public bool IsTempId(UniqueId uniqueId) {
      if (_tempIds == null) {
        return false;
      }
      return _tempIds.Contains(uniqueId);
    }

    /// <summary>
    /// Called by DevForce after an EntityManager.SaveChanges call is performed and all temporary Id values
    /// have been "fixed up" as real Ids.  Use this to clear your temporary Id collection and reset counters.
    /// </summary>
    public void Reset() {
      _tempIds.Clear();
      _nextBaseId = 0;
    }

    /// <summary>
    /// Called by DevForce from the BOS to retrieve "real" Id values for the temporary Ids passed.
    /// </summary>
    /// <remarks>
    /// You can retrieve "real" Ids in any manner you like - this sample shows allocation
    /// of Ids from a single table holding a global sequence value.
    /// You must return a UniqueIdMap from this method containing a real Id value for each
    /// temporary Id.  Note that the UniqueId objects passed in contain information on the
    /// EntityColumn used.  You can use this information to perform more complex Id allocation
    /// if needed.
    /// Because this method is called from the server, and the server is multi-threaded,
    /// you must provide synchronization logic to handle concurrent requests.  In this
    /// sample, a lock is used within the GetNextId logic.
    /// </remarks>
    public UniqueIdMap GetRealIdMap(UniqueIdCollection tempIds, IDataSourceKey dataSourceKey ) {

      UniqueIdMap idMap = new UniqueIdMap();

      long nextLongId = GetNextId(tempIds.Count, dataSourceKey);
      object nextId;

      // Build a UniqueIdMap containing the mapping of temporary to real Id values.
      foreach (UniqueId aUniqueId in tempIds) {
        try {
          nextId = Convert.ChangeType(nextLongId, aUniqueId.Property.DataType);
        } catch {
          throw new NotSupportedException("This id generator cannot generate ids of type " + aUniqueId.Property.DataType);
        }

        idMap.Add(aUniqueId, nextId);
        nextLongId++;
      }

      return idMap;
    }

    #region Server-side custom Id allocation

    /// <summary>
    /// Perform allocation and return the starting next Id value.
    /// This sample disallows Id allocation for more than MaxGroupSize (1000) values
    /// at a time.  It also always allocates 100 new values at a time.
    /// These numbers are arbitrary, and for illustration only.  
    /// </summary>
    private long GetNextId(int count, IDataSourceKey dataSourceKey) {

      // Serialize access to GetNextId - the BOS is multi-threaded and concurrent saves can be in progress.
      lock (__syncLock) {

        // Do some validation before proceeding.
        TraceFns.Assert(count > 0, "GetNextId requires a positive integer as its arg.");

        TraceFns.Assert(count <=  MaxGroupSize,"Cannot allocate more than "
          + MaxGroupSize + " in any one call to GetNextId");

        // Allocate more Ids only if necessary.  This allocates 100 at a time.
        if (__nextId + count > __maxNextId) {
          AllocateMoreIds(count, dataSourceKey);
        }

        long result = __nextId;
        __nextId += count;        // Next time we'll start here.
        return result;
      }
    }

    /// <summary>
    /// Allocate more "real" Id values.  This sample uses a table called NextId with
    /// "Name" and "NextId" columns.  It uses a "global" allocation strategy - that is,
    ///  Id values are not assigned on a table-specific basis, but globally within the application.
    /// </summary>
    private void AllocateMoreIds(int count, IDataSourceKey dataSourceKey) {
      const String sqlSelect = "select NextId from NextId where Name = 'GLOBAL'";
      const String sqlUpdate = "update NextId set NextId={0} where Name = 'GLOBAL' and NextId={1}";

      // Allocate the larger of the two:  amount requested or the default alloc group size.
      count = Math.Max(count, DefaultGroupSize);

      AdoHelper adoHelper = GetAdoHelper(dataSourceKey);
      IDbConnection aConnection = adoHelper.CreateDbConnection(true);
      aConnection.Open();

      using (aConnection) {
        IDbCommand selectCommand =  adoHelper.CreateDbCommand(aConnection);
        IDbCommand updateCommand = adoHelper.CreateDbCommand(aConnection);

        for (int trys = 0 ; trys <= MaxTrys ; trys++) {
          
          selectCommand.CommandText = sqlSelect;    
          IDataReader aDataReader = selectCommand.ExecuteReader();
          if (!aDataReader.Read()){
            throw new ApplicationException("Unable to locate 'NextId' record");
          }

          Object tmp = aDataReader.GetValue(0);
          long nextId = (long) Convert.ChangeType(tmp, typeof(Int64));
          long newNextId = nextId + count;
          aDataReader.Close();

          // Update the table to reflect the new NextId value to be assigned next time.
          updateCommand.CommandText = String.Format(sqlUpdate, newNextId, nextId);
         
          // If only one record was affected - we're ok; otherwise try again.
          if (updateCommand.ExecuteNonQuery() == 1) {
            __nextId = nextId;
            __maxNextId = newNextId;
            return;
          }
        }
      }
      throw new ApplicationException("Unable to generate a new id");
    }

    /// <summary>
    /// Retrieve an AdoHelper to use in data access.  This sample issues
    /// select and update commands to the database, using the AdoHelper.
    /// </summary>
    private AdoHelper GetAdoHelper(IDataSourceKey dataSourceKey) {

      // Option 1 - if you want to reference both IdeaBlade.EntityModel.Edm.v4
      //  and IdeaBlade.Rdb.v4 assemblies.
      IdeaBlade.EntityModel.Edm.EdmKey edmKey =
        dataSourceKey as IdeaBlade.EntityModel.Edm.EdmKey;
      RdbKey rdbKey = edmKey.RdbKey as RdbKey;
      return rdbKey.AdoHelper;


      // Option 2 - you might not want to reference the IdeaBlade.EntityModel.Edm.v4 assembly on your
      //  client (since it in turn references Entity Framework assemblies).  You could instead use
      //  a little reflection.
      //      Type t = InternalFns.GetIdeaBladeType("IdeaBlade.EntityModel.Edm.v4.EdmKey", true);
      //      RdbKey rdbkey = t.GetProperty("RdbKey").GetValue(dataSourceKey, null) as RdbKey;
      //      return rdbkey.AdoHelper;


      // Option 3 - You can create separate client-side vs. server-side IdGenerator implementations.
      //  Contact IdeaBlade for more information.

    }
    #endregion

    // Client-side variables.
    [DataMember]
    private UniqueIdCollection _tempIds = new UniqueIdCollection();
    [DataMember]
    private int _nextBaseId;

    private const int  MaxTrys           = 3;       // Fail after 3 unsuccessful allocation attempts.
    private const int  DefaultGroupSize  = 100;     // Allocate 100 new Ids at a time.
    private const int  MaxGroupSize      = 1000;    // Only allow 1000 Ids max in a call.

    // Server-side variables.
    private static object __syncLock = new object();
    private static long __nextId       = 0;
    private static long __maxNextId    = 0;
   
  }
}
 
Back to Top
pucsoftware View Drop Down
Groupie
Groupie
Avatar

Joined: 15-Apr-2008
Location: United States
Posts: 46
Post Options Post Options   Quote pucsoftware Quote  Post ReplyReply Direct Link To This Post Posted: 03-Feb-2010 at 8:21am
In DevForce v5.2.4.2 on Windows 7 we found the sample class, both C# & VB versions, installed here:
 
C:\Users\Public\Documents\DevForce\Learning Resources\040_BusObjPersistence\AddingDeleting\Snippets\NumericIdGenerator
 
This may be useful if you're looking for the VB version.
puctx
Back to Top
tj62 View Drop Down
Groupie
Groupie
Avatar

Joined: 21-May-2009
Location: Iceland
Posts: 81
Post Options Post Options   Quote tj62 Quote  Post ReplyReply Direct Link To This Post Posted: 03-Jan-2011 at 7:55am
I have searched all over the place on my computer and it is not there the LearningResources folder does not exist. Except I find it for an old 2009 installatoin at:
    C:\Program Files\IdeaBlade DevForce\Learning Resources
But the current installatoin is at:
    C:\Program Files\DevForce 2010
where there is no Learning Resources folder at all.
 
Where in heck is it?
Back to Top
davidklitzke View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 14-Jun-2007
Posts: 715
Post Options Post Options   Quote davidklitzke Quote  Post ReplyReply Direct Link To This Post Posted: 03-Jan-2011 at 9:45am

If you are looking at DevForce 2009, you can find the files at a location such as:

 C:\Program Files\IdeaBlade DevForce\Learning Resources\040_BusObjPersistence\AddingDeleting\Snippets\NumericIdGenerator

If you are looking at DevForce 2010, the files are not where you might expect them to be (i.e., in the "030_BusObjPersistence\AddingDelecting" folder).  However you can find both C# and VB versions in the "030_BusObjPersistence\_MiniDemos" folder.

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down