views:

415

answers:

3

I have an object with the following properties


GID
ID
Code
Name

Some of the clients dont want to enter the Code so the intial plan was to put the ID in the code but the baseobject of the orm is different so I'm like screwed...

my plan was to put ####-#### totally random values in code how can I generate something like that say a windows 7 serial generator type stuff but would that not have an overhead what would you do in this case.

A: 

You could generate a Guid using :

Guid.NewGuid().ToString();

It would give you something like :

788E94A0-C492-11DE-BFD4-FCE355D89593

Manitra Andriamitondra
this is ok ? I have index on Code so if a same say 788E94A0-C492 appeared ?
abmv
Check database if the one you generated already exists, if it does, generate again. The algorithm for creating a GUID is very good.
Yuriy Faktorovich
only a complete value has any guarantees of global uniqueness, and truncation is a *lossful* transformation. if you truncate something you are effectively diminishing the domain of possible values - and increasing the likelihood of generating the same value. DO NOT TRUNCATE Guids.
johnny g
Don't truncate the guid, your insertion will fail only 1 time every 3*10^38 inserts. The risk is okay in most cases.
Manitra Andriamitondra
-2? Isn't that a little harsh, when a quick check and regeneration would do the trick.
Yuriy Faktorovich
best case scenario, you are correct. unfortunately if your Guid generation is sequential - and i've seen this elsewhere [eg databases] - you could be rechecking a *very* long time. of course, a proper .Net implementation is a black-box, but it still stands to reason. after all, although more complex than sequential, .Net's Guid generator *deterministically generates Guids*. when it comes to performance *and* correctness, close doesn't count - er, and a pre-emptive apology, i am not trying to be mean, just straight :S
johnny g
A: 

Use an Autonumber column or Sequencer from your database to generate a unique code number. Almost all modern databases support automatically generated numbers in one form or another. Look into what you database supports.

Autonumber/Sequencer values from the DB are guaranteed to be unique and are relatively inexpensive to acquire. If you want to avoid completely sequential numbers assigned to codes, you can pad and concatenate several sequencer values together.

LBushkin
I have an orm and need to support all databases in the world ;-) (mostly kidding)
abmv
+1  A: 

Do you want a random value, or a unique value?

random != unique.

Remember, random merely states a probability of not generating the same value, or a probability of generating the same value again. As time increases, likelihood of generating a previous value increases - becoming a near certainty. Which do you require?

Personally, I recommend just using a Guid with some context [refer to easiest section below]. I also provided some other suggestions so you have options, depending on your situation.


easiest

If Code is an unbounded string [ie can be of any length], easiest semi-legible means of generating a unique code would be

OrmObject ormObject= new OrmObject ();
string code = string.
    Format ("{0} [{1}]", ormObject.Name, Guid.NewGuid ()).
    Trim ();
// generates something like
// "My Product [DA9190E1-7FC6-49d6-9EA5-589BBE6E005E]"

you can substitute ormObject.Name for any distinguishable string. I would typically use typeof (objectInstance.GetType ()).Name but that will only work if OrmObject is a base class, if it's a concrete class used for everything they will all end up with similar tags. The point is to add some user context, such that - as in @Yuriy Faktorovich's referenced wtf article - users have something to read.


random

I responded a day or two ago about random number generation. Not so much generating numbers as building a simple flexible framework around a generator to improve quality of code and data, this should help streamline your source.

If you read that, you could easily write an extension method, say

public static class IRandomExtensions
{
    public static CodeType GetCode (this IRandom random)
    {
        // 1. get as many random bytes as required
        // 2. transform bytes into a 'Code'
        // 3. bob's your uncle
        ...
    }
}

    // elsewhere in code
    ...
    OrmObject ormObject = new OrmObject ();
    ormObject.Code = random.GetCode ();
    ...

To actually generate a value, I would suggest implementing an IRandom interface with a System.Security.Cryptography.RNGCryptoServiceProvider implementation. Said implementation would generate a buffer of X random bytes, and dole out as many as required, regenerating a stream when exhausted.

Furthermore - I don't know why I keep writing, I guess this problem is really quite fascinating! - if CodeType is string and you want something readable, you could just take said random bytes and turn them into a "seemingly" readable string via Base64 conversion

public static class IRandomExtensions
{
    // assuming 'CodeType' is in fact a string
    public static string GetCode (this IRandom random)
    {
        // 1. get as many random bytes as required
        byte[] randomBytes; // fill from random
        // 2. transform bytes into a 'Code'
        string randomBase64String = 
            System.Convert.ToBase64String (randomBytes).Trim ("=");
        // 3. bob's your uncle
        ...
    }
}

Remember

random != unique.

Your values will repeat. Eventually.


unique

There are a number of questions you need to ask yourself about your problem.

  1. Must all Code values be unique? [if not, you're trying too hard]
  2. What Type is Code? [if any-length string, use a full Guid]
  3. Is this a distributed application? [if not, use a DB value as suggested by @LBushkin above]
  4. If it is a distributed application, can client applications generate and submit instances of these objects? [if so, then you want a globally unique identifier, and again Guids are a sure bet]

I'm sure you have more constraints, but this is an example of the kind of line of inquiry you need to perform when you encounter a problem like your own. From these questions, you will come up with a series of constraints. These constraints will inform your design.

Hope this helps :)

Btw, you will receive better quality solutions if you post more details [ie constraints] about your problem. Again, what Type is Code, are there length constraints? Format constraints? Character constraints?

Arg, last edit, I swear. If you do end up using Guids, you may wish to obfuscate this, or even "compress" their representation by encoding them in base64 - similar to base64 conversion above for random numbers.

public static class GuidExtensions
{
    public static string ToBase64String (this Guid id)
    {
        return System.Convert.
            ToBase64String (id.ToByteArray ()).
            Trim ("=");
    }
}

Unlike truncating, base64 conversion is not a lossful transformation. Of course, the trim above is lossful in context of full base64 expansion - but = is just padding, extra information introduced by the conversion, and not part of original Guid data. If you want to go back to a Guid from this base64 converted value, then you will have to re-pad your base64 string until its length is a multiple of 4 - don't ask, just look up base64 if you are interested :)

johnny g
well i just need the code value to be unique cause i have an index on it the,some customers will use code while other customers have no use of code so the customer who do not use it will feel a pain to add code to each data entry.so the above unique will generate a unique base64? i just need to put a unique string in there...
abmv
made a quick edit at top of answer, see recommendation and easiest section.
johnny g
Using a Guid will give you de facto unique values, because Guids are sufficiently long that even taking the birthday paradox into account, you'll probably never actually have a collision.
Brian