Generate 8 digit uinque id in c#

2020-07-13 10:32发布

I need to generate 8 digit unique id in c#. On my site a user will register and I need to generate a unique id for him in c# code(I don't want this logic in DB), after inserting the id I need to save it in database.

Edit: I need that numbers to be generated in random manner everytime.

标签: c# asp.net
7条回答
甜甜的少女心
2楼-- · 2020-07-13 10:53

Use Sequential Guids! Reduces the probability of a clash where guids already have a low probability of clashing and also means you can order your data by the Guid, representing the time of insertion.

    [DllImport("rpcrt4.dll", SetLastError = true)]
    static extern int UuidCreateSequential(out Guid guid);

    public static Guid SequentialGuid()
    {
        const int rpcSOk = 0;
        Guid guid;

        return UuidCreateSequential(out guid) != rpcSOk ? Guid.NewGuid() : guid;
    }

You can put this method in the base class for customers, or all entities and have it generated automagically in the base constructor on instatiation.

查看更多
看我几分像从前
3楼-- · 2020-07-13 10:53

You can also use my identify generator. But it's not integer one unfortunately. Make sure you have case sensitive ID column in db otherwise change the character range. The identifier is url friendly. Based on partial DateTime Ticks (10 characters) and partial Random (6 characters). It's not sortable so use AddedDate column instead to get a row sequence. Use varchar(16) column type and SQL_Latin1_General_CP1_CS_AS collation.

public static class IdentifyGenerator
{
    private static char[] sybmols = { 
                             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                             'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
                         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                         };

    public static string WebHash()
    {
        int length = sybmols.Length;
        ulong num = (ulong)DateTime.Now.Ticks;

        string output = string.Empty;
        ulong tmp = num;
        ulong mod = 0;
        while (tmp != 0)
        {
            mod = tmp % (ulong)length;
            tmp = tmp / (ulong)length;
            output = sybmols[mod] + output;
        }
        output += RandomString(6);
        return output;
    }

    public static string RandomString(int length)
    {
        Stack<byte> bytes = new Stack<byte>();
        string output = string.Empty;

        for (int i = 0; i < length; i++)
        {
            if (bytes.Count == 0)
            {
                bytes = new Stack<byte>(Guid.NewGuid().ToByteArray());
            }
            byte pop = bytes.Pop();
            output += sybmols[(int)pop % sybmols.Length];
        }
        return output;
    }
}

Unit Test:

[TestClass]
public class Code
{
    [TestMethod]
    public void IdentifyGeneratorTest()
    {
        var set = new HashSet<string>();
        for (int i = 1; i <= 1000000; i++)
        {
            var id = IdentifyGenerator.WebHash();
            if (!set.Add(id))
                Assert.Fail("IdentifyGenerator duplicate found");
        }
    }
}

Good luck.

查看更多
Luminary・发光体
4楼-- · 2020-07-13 10:57

You can use Random Class

Random r=new Rand();
int id;
while((id=r.Next(10000000,99999999))!=someId); //check in database that Id is unique

Always remember that there is no technique to generate a unique Random number without checking existing values in database

You must have some information regarding previous values

查看更多
一纸荒年 Trace。
5楼-- · 2020-07-13 11:03

You could try to implement a method that generates a random number but you have always to check if it is already in database.

    static void Main(string[] args)
    {
        HashSet<string> numbers = new HashSet<string>();

        for (int i = 0; i < 100; i++)
        {
            numbers.Add(GenerateRandomNumber(8));
        }

        Console.WriteLine(numbers.Count == 100);
        Console.ReadLine();
    }

    static Random random = new Random();

    static string GenerateRandomNumber(int count)
    {
        StringBuilder builder = new StringBuilder();

        for (int i = 0; i < count; i++)
        {
            int number = random.Next(10);
            builder.Append(number);
        }

        return builder.ToString();
    }
查看更多
爱情/是我丢掉的垃圾
6楼-- · 2020-07-13 11:06

If you don't mind the IDs being predictable, I'd go with Vlad's suggestion.

Otherwise, I'd generate a random number in the required range and just try to insert it in the database... if you get an exception due to the uniqueness constraint being violated in the database (and that constraint absolutely should be there) then try again. Keep trying until it either works or you've gone round a certain number of times. (It's highly unlikely that you'll fail 100 times for example - unless you've got a bug elsewhere, in which case an exception is preferable to an infinite loop.)

So this isn't generating the ID in the database - but it's verifying the uniqueness in the database, which is after all the ultimate "source of truth".

If you don't need cryptographically securely generated IDs, then simply using Random.Next(100000000) will generate you a value in the range [0, 99999999]. If you don't want any values which need leading 0s to get to 8 digits, simply use Random.Next(10000000, 100000000) which will give you a smaller range of possible values, but you won't need to worry about them having fewer than 8 digits.

Using Random properly has a few "gotchas" - see my article about it for more details.

查看更多
我命由我不由天
7楼-- · 2020-07-13 11:12

Why not just keep the last allocated number and increase it by 1 when allocating a new ID? Interlocked.Increment might be useful. You can pad the number with zeroes at the left to the 8 digits. Using int as backing type should be enough.

Edit: if you want the number to look random, just store in the DB not the allocated sequential numbers themselves, but use some bijective mapping. For example, you can store 7461873*ID + 17845612 instead. This guarantees the uniqueness and looks random.

By the way, this is similar how the random number generators usually work (only they don't use the sequential number, but rather the result of previous calculation).

查看更多
登录 后发表回答