Generowanie quasi unikalnych kodów

0

Potrzebuję jakiegos sposobu na generowanie przyjaznych dla użytkownika, quasi unikalnych kodów. Chodzi np. o wygenerowanie numeru zamówienia. Stopień unikalność nie musi być taki jak w Guid, ważne żeby prawdopodobieństwo duplikatu było stosunkowo niskie. Unikalność danych zapewni unique constraint w bazie danych.

Idealnie by było gdyby kod był krótki, ok. 5 znaków alfanumerycznych. Ktoś ma pomysł jak to najlepiej osiągnąć?

1

A nie lepiej jechac: a0000, a1000, I tak dalej.

0

Do czego konkretnie potrzebujesz tych kodów?

1

Jak to ma być jakiś numer zamówienia to możesz dać id użytkownika+kawałek timstamp. Raczej jeden użytkownik nie dokona zamówienia więcej niż 1 razy na sek.

0

Chodzi o numer zamówienia, nie ma uwierzytelniania użytkownika jako że zamówienie jak i opłata mogą zostać dokonane bez założenia konta.

Tak, "losowanie" jak najbardziej jest dobrą opcją tylko że właśnie jak to losować? Chodzi o to żeby w 50% przypadków nie dostawać wyjątku z bazy danych i próbować na nowo, bo to się odbije na wydajności i user experience.

Trzymanie i generowanie sekwencji w bazie danych może być jedną z opcji - wie ktoś jak najlepiej do tego podejść? Tzn jak wziąć sekwencyjny int z bazy danych, na jego postawie stworzyć kod (string zawierający numer sekwencyjny) i zapisać to tak aby w tym samym czasie ktoś nie wyciągnął tego samego numeru i nie spróbował również go użyć? Ujmując to inaczej - jak zwiększyć wartość numeru w bazie przy wyciąganiu go, a nie zapisywaniu?

Idealnie numer zamowienia powinien byc w miare ciezki do odgadniecia, a wiec jakis numery sekwencyjny moze byc jego czescia, ale caly numer nie powinien sie na nim opierac.

1

Niech numer zamówienia będzie automatycznie inkrementującym się id, lecz do otworzenia zamówienia niech będzie wymagane dodatkowo hasło - np. osiem automatycznie wygenerowanych znaków.

Dzięki takiemu podejściu tylko krotka (id, hasło) musi być unikalna - hasło samo w sobie już nie.

Coś takiego ma np. OVH i, jak widać, sprawdza się ;-)

0

Id odpada poniewaz jest nim Guid (ID moze byc uzywane przez rozne serwisy). Sama idea automatycznie wygenerowanych znakow to jest dokladnie to czego potrzebuje i dokladnie to o co pytam- jak to zrobic? :) Chodzi mi o szczegoly implementacyne, lub idealnie jakas biblioteka jesli ktos taka zna. Idealnym rozwiazaniem byla by jakas prosta biliboteka po ktorej za pierwszym przywolaniem dostane wynik "ABCDE123", za drugim "HJKDS645" itd. A wiec calkowita losowsc z niskim prawdopodobienstwem duplikatu.

2

Wygeneruj pseudolosową liczbę, policz jej MD5 / SHA / ..., zamień na wartość heksadecymalną i weź pierwsze n znaków :-P

Nie nadaje się to do zastosowań kryptograficznych (ponieważ ograniczamy przeciwdziedzinę funkcji haszhującej), lecz w tym wypadku powinno wystarczyć.

0

Czas to jest coś unikalnego, użyj liczby pikosekund od początku wszechświata i to chyba powinno być unikalne, ;-).

0

Koniec koncow poszedlem prosta droga i generuje numer zamowienia w oparciu o znaki alfanumeryczne. Kod wyglada tak:

    public static class OrderNumberGenerator
    {
        private const string AlphaCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        private const string NumericCharacters = "1234567890";

        public static string Generate()
            => string.Concat(
                GetRandomString(AlphaCharacters, 5),
                GetRandomString(NumericCharacters, 3)
            );

        private static string GetRandomString(string source, int charactersLength)
        {
            var builder = new StringBuilder();

            for (var i = 0; i < charactersLength; i++)
            {
                var characterIndex = new Random().Next(0, source.Length - 1);
                builder.Append(source[characterIndex]);
            }

            return builder.ToString();
        }
    }

W testach na 100k wygenerowanych liczb trafia sie 1 duplikat, wiec prawdopodobienstwo wynoszace 0.00001% jest zadowalajace w tym przypadku.

0

Kod musi powstać w wyniku mieszania nie powtarzających się danych początkowych i danych które mogą się powtórzyć
. Dane które się nie powtórzą to może być np. bieżący czas wyrażony w milisekundach , numer porządkowy , dane, które mogą się powtórzyć to np. imię , nazwisko wiek ,
Doby algorytm mieszania to zadanie bardziej dla matematyka niż informatyka .

0
Zimny Krawiec napisał(a):

Kod musi powstać w wyniku mieszania nie powtarzających się danych początkowych i danych które mogą się powtórzyć
. Dane które się nie powtórzą to może być np. bieżący czas wyrażony w milisekundach , numer porządkowy , dane, które mogą się powtórzyć to np. imię , nazwisko wiek ,
Doby algorytm mieszania to zadanie bardziej dla matematyka niż informatyka .

Dobra teoretyczna wstawka, ja również wyznaję pogląd, że numer dla użytkownika powinien zawierać oprócz unikalności dodatkowe informacje, np. rok/miesiąc/numer_kolejny_w_ramach_roku_miesiaca lub identyfikator_sprzedawcy/rok/....., a generatory z d**y dające niezrozumiałe ciągi niech służą kandydatom na programistów w szlifowaniu mózgu.

0

"Po co matematyk ? " - bo to jest zagadnienie matematyczne , Programista musi tylko przełożyć daną koncepcję na język programowania .
Jak się komuś nie podoba mój pomysł albo uważa, że jest niewystarczający to powinien zrobić bazę wykorzystanych kodów i sprawdzać za każdym razem czy kod był już wcześniej użyty

0

@Aventus: piszesz do nas z UK, więc powinieneś to zrobić tak, jak się w UK robi (kod oryginalny, tylko nazwa tabeli zmieniona):

WHILE(1=1)
BEGIN
    SET @Seqno = REPLACE(STR(RAND() * 10000000, 7, 0), ' ', 0)            

    IF NOT EXISTS (SELECT 1 FROM MyTable WITH (TABLOCK, HOLDLOCK) WHERE SequenceNo = @Seqno AND GenerationDate = @generationDate)
        BREAK;
END

Oczywiście w SQL, bo "tak jest wydajniej". Co z tego, że procedura i tak odpalana z aplikacji, więc np. wygenerowanie 50k wpisów wywala program, bo przekracza domyślny czas transakcji w .NET (20 minut). ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1