Author |
Share Topic Topic Search Topic Options
|
davidklitzke
IdeaBlade
Joined: 14-Jun-2007
Posts: 715
|
Post Options
Quote Reply
Topic: Where can I find document for how to implement the GenerateID() interface? 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.
|
|
tj62
Groupie
Joined: 21-May-2009
Location: Iceland
Posts: 81
|
Post Options
Quote Reply
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?
|
|
pucsoftware
Groupie
Joined: 15-Apr-2008
Location: United States
Posts: 46
|
Post Options
Quote Reply
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
|
|
GregD
IdeaBlade
Joined: 09-May-2007
Posts: 374
|
Post Options
Quote Reply
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; } }
|
|
davidklitzke
IdeaBlade
Joined: 14-Jun-2007
Posts: 715
|
Post Options
Quote Reply
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.
|
|
dpollot44
Newbie
Joined: 13-Jan-2010
Location: Rochester NY
Posts: 24
|
Post Options
Quote Reply
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).
|
|
dpollot44
Newbie
Joined: 13-Jan-2010
Location: Rochester NY
Posts: 24
|
Post Options
Quote Reply
Posted: 13-Jan-2010 at 12:35pm |
I reinstalled. The full/vs. custom install didn't include the learning units.
|
|
dpollot44
Newbie
Joined: 13-Jan-2010
Location: Rochester NY
Posts: 24
|
Post Options
Quote Reply
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?
|
|
GregD
IdeaBlade
Joined: 09-May-2007
Posts: 374
|
Post Options
Quote Reply
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
|
|
dpollot44
Newbie
Joined: 13-Jan-2010
Location: Rochester NY
Posts: 24
|
Post Options
Quote Reply
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)
|
|
GregD
IdeaBlade
Joined: 09-May-2007
Posts: 374
|
Post Options
Quote Reply
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.
|
|
Suah
Newbie
Joined: 06-Jul-2009
Posts: 16
|
Post Options
Quote Reply
Posted: 20-Aug-2009 at 9:52pm |
Where can I find document for how to implement the GenerateID() interface?
|
|