Попытка создать несколько уникальных коротких URL - PullRequest
2 голосов
/ 17 февраля 2020

Я хочу создать метод публикации, который возвращает список сокращенных URL-адресов, когда ему дано тело, содержащее несколько URL-адресов в JSON.

Это мой метод публикации:

public class MyServices : Service
{
    public object Post(CreateShortUrlRequest request) //Post an array/list of URLs to the database and get a respective list of short URL
    {
        using (Task4URLEntities db = new Task4URLEntities())
        {
            var urls = new List<string>();
            foreach (string LongUrl in request.LongUrl)
            {
                var item = new ShortURLs
                {
                    LongUrl = LongUrl,
                    ShortUrl = GetUrl(),
                    DateCreated = DateTime.Now
                };
                urls.Add($"http://localhost/{item.ShortUrl}");
                db.ShortURLs.Add(item);
            }

            var campaign = new Campaign
            {
                CampaignName = request.CampaignName,
                Enddate = request.Enddate,
                Startdate = request.Startdate
            };

            db.Campaign.Add(campaign);

            try
            {
                db.SaveChanges();
            }
            catch (DbEntityValidationException ex)
            {
                foreach (var entityValidationErrors in ex.EntityValidationErrors)
                {
                    foreach (var validationError in entityValidationErrors.ValidationErrors)
                    {
                        Response.WriteAsync("Property: " + validationError.PropertyName + " Error: " + validationError.ErrorMessage);
                    }
                }
            }

            return new CreateShortUrlResponse
            {
                Response = urls,
                CampaignId = campaign.CampaignId
            };
        }
    }

    public string GetUrl()
    {
        var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        var stringChars = new char[5];
        var random = new Random();
        for (int i = 0; i < stringChars.Length; i++)
        {
            stringChars[i] = chars[random.Next(chars.Length)];
        }
        var finalString = new String(stringChars);
        return finalString;
    }

 }

Моя проблема заключается в том, что когда я отправляю свой запрос на публикацию в «Почтальоне» списка URL-адресов в JSON, я получу уникальные URL-адреса в качестве ответа на первое сообщение, если я снова нажму кнопку «Отправить», то получу ответ, в котором каждый возвращенный короткий URL-адрес это то же самое.

Как я могу исправить это?

1 Ответ

2 голосов
/ 17 февраля 2020

Я предполагаю, что когда вы говорите "каждый возвращенный короткий URL-адрес один и тот же", вы имеете в виду, что свойство CreateShortUrlResponse.Response содержит точно такой же URL-адрес n число раз, где n - это количество URL-адресов, которые вы запросили. Исходя из этого, я также предполагаю, что это проект. NET Framework, а не. NET Базовый проект.

Если это так, то проблема заключается в том, что создание нового экземпляры Random в таком узком l oop приводят к тому, что каждый из них создается с одинаковым начальным значением. Когда вы создаете экземпляр Random в. NET Framework с пустым конструктором, он использует Environment.TickCount в качестве начального числа. Итак, если вы создадите два экземпляра Random в быстрой последовательности, они оба будут иметь одинаковое начальное число и, следовательно, сгенерируют одинаковые значения.

Документация на Random говорит об этом .

На платформе. NET при инициализации двух генераторов случайных чисел в узкой последовательности l oop или в быстрой последовательности создаются два генератора случайных чисел, которые могут создавать идентичные последовательности случайных чисел. В большинстве случаев это не является намерением разработчика и может привести к проблемам с производительностью, поскольку создание и инициализация генератора случайных чисел является относительно дорогим процессом.

Как для повышения производительности, так и для предотвращения случайного создания отдельных генераторов случайных чисел которые генерируют идентичные числовые c последовательности, мы рекомендуем вам создать один объект Random для генерации множества случайных чисел во времени, а не создавать новые объекты Random для генерации одного случайного числа.

Однако класс Random isn ' Это безопасно. Если вы вызываете методы Random из нескольких потоков, следуйте рекомендациям, обсуждаемым в следующем разделе.

Таким образом, вы можете сделать экземпляр Random членом класса MyServices вместо создания нового экземпляр каждый раз, когда вы звоните GetUrl.

public class MyServices : Service
{
    public object Post(CreateShortUrlRequest request) //Post an array/list of URLs to the database and get a respective list of short URL
    {
        using (Task4URLEntities db = new Task4URLEntities())
        {
            var urls = new List<string>();
            foreach (string LongUrl in request.LongUrl)
            {
                var item = new ShortURLs
                {
                    LongUrl = LongUrl,
                    ShortUrl = GetUrl(),
                    DateCreated = DateTime.Now
                };
                urls.Add($"http://localhost/{item.ShortUrl}");
                db.ShortURLs.Add(item);
            }

            var campaign = new Campaign
            {
                CampaignName = request.CampaignName,
                Enddate = request.Enddate,
                Startdate = request.Startdate
            };

            db.Campaign.Add(campaign);

            try
            {
                db.SaveChanges();
            }
            catch (DbEntityValidationException ex)
            {
                foreach (var entityValidationErrors in ex.EntityValidationErrors)
                {
                    foreach (var validationError in entityValidationErrors.ValidationErrors)
                    {
                        Response.WriteAsync("Property: " + validationError.PropertyName + " Error: " + validationError.ErrorMessage);
                    }
                }
            }

            return new CreateShortUrlResponse
            {
                Response = urls,
                CampaignId = campaign.CampaignId
            };
        }
    }

    public string GetUrl()
    {
        var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        var stringChars = new char[5];
        for (int i = 0; i < stringChars.Length; i++)
        {
            stringChars[i] = chars[_rng.Next(chars.Length)];
        }
        var finalString = new String(stringChars);
        return finalString;
    }
    private Random _rng = new Random();
 }
...