Последовательный GUID в Linq-to-Sql?

Если вы не хотите использовать aggregate, другое решение должно использовать find, а затем сортировать результаты на стороне клиента с помощью array#sort :

Если значения $in являются примитивными типами, такими как числа, вы можете использовать такой подход, как:

var ids = [4, 2, 8, 1, 9, 3, 5, 6];
MyModel.find({ _id: { $in: ids } }).exec(function(err, docs) {
    docs.sort(function(a, b) {
        // Sort docs by the order of their _id values in ids.
        return ids.indexOf(a._id) - ids.indexOf(b._id);
    });
});

Если значения $in являются непримитивными типами, например ObjectId s, требуется другой подход поскольку indexOf сравнивается по ссылке в этом случае.

Если вы используете Node.js 4.x +, вы можете использовать Array#findIndex и ObjectID#equals , чтобы отрегулировать это, изменив функцию sort на:

docs.sort((a, b) => ids.findIndex(id => a._id.equals(id)) - 
                    ids.findIndex(id => b._id.equals(id)));

Или с любой версией Node.js, с подчеркиванием / lodash's findIndex :

docs.sort(function (a, b) {
    return _.findIndex(ids, function (id) { return a._id.equals(id); }) -
           _.findIndex(ids, function (id) { return b._id.equals(id); });
});

20
задан JacobE 20 March 2009 в 09:07
поделиться

5 ответов

РАСЧЕСКИ сгенерированы следующий путь:

DECLARE @aGuid UNIQUEIDENTIFIER

SET @aGuid = CAST(CAST(NEWID() AS BINARY(10)) + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)

то, Которое записало в C#, будет похоже на это:

    public static unsafe Guid CombGuid()
    {
        Guid guid = Guid.NewGuid();
        byte[] bytes = guid.ToByteArray();
        long ticks = DateTime.Now.Ticks;
        fixed( byte* pByte = bytes )
        {
            int*    pFirst  = (int *)(pByte + 10);
            short* pNext    = (short*)(pByte + 14);
            *pFirst = (int)(ticks & 0xFFFFFF00);
            *pNext  = (short)ticks;
        }

        return new Guid( bytes );
    }
9
ответ дан 29 November 2019 в 22:43
поделиться

Ну, Вы могли генерировать Guid вручную. Однако одно из преимуществ Guid - то, что это не является отгадываемым - т.е. данная запись 0000-...-0005, обычно существует мало точки (от взломщика) проверяющий на запись 0000-....-0004 и т.д.

Также - фрагментация ре? Пока у Вас есть некластерный индекс на этих данных, я не уверен, что это - проблема. Вы обычно не помещали бы кластерный индекс на Guid, таким образом, таблица будет "кучей" (если у Вас не будет отдельного кластерного индекса, такой как IDENTITY интервал). В этом случае Вы будете добавлять до конца и вставлять новое Guid в некластерный индекс. Никакая реальная боль.

(редактирование) Одна проблема использования времени непосредственно состоит в том, что Вы представляете намного больше риска коллизий; необходимо было бы волноваться о жестком цикле Guid создание (т.е. повторение предотвращения при создании некоторых в последовательности), что означает синхронизацию, и т.д. - и это становится еще более неприятным, если несколько машин работают интенсивно параллельно - возможности, Вы получите дубликаты.

3
ответ дан 29 November 2019 в 22:43
поделиться

Вот несколько статей:

Из Введение в динамический SQL :

Динамический SQL - термин, используемый для обозначения кода SQL, который генерируется программой программно (частично или полностью) перед его выполнением. В результате это очень гибкий и мощный инструмент. Динамический SQL можно использовать для выполнения таких задач, как добавление предложений where в поиск на основе того, какие поля заполняются в форме, или для создания таблиц с различными именами.

-121--2853423-

Попробуйте использовать Java 1,4:

for( Iterator entries = myMap.entrySet().iterator(); entries.hasNext();){

  Entry entry = (Entry) entries.next();

  System.out.println(entry.getKey() + "/" + entry.getValue());

  //...
}
-121-1893569-

Вы всегда можете вызвать UuidCreateSequential; это «старый» генератор guid (до 2000-х годов, когда MSFT изменил его на более случайные направляющие стиля, к которым мы привыкли сегодня). Они переименовали старый UuidCreate в UuidCreateSequential и включили новый генератор guid в новую реализацию UuidCreate. UuidCreateSequential также используется SQL Server в NewSequentityID (), и он является таким же уникальным, как обычные направляющие, но с тем преимуществом, что они являются последовательными, если создать их стопку в строке в том же процессе.

using System;
using System.Runtime.InteropServices;

namespace System
{
    public static class GuidEx
    {
        [DllImport("rpcrt4.dll", SetLastError = true)]
        private static extern int UuidCreateSequential(out Guid guid);
        private const int RPC_S_OK = 0;

        /// <summary>
        /// Generate a new sequential GUID. If UuidCreateSequential fails, it will fall back on standard random guids.
        /// </summary>
        /// <returns>A GUID</returns>
        public static Guid NewSeqGuid()
        {
            Guid sequentialGuid;
            int hResult = UuidCreateSequential(out sequentialGuid);
            if (hResult == RPC_S_OK)
            {
                return sequentialGuid;
            }
            else
            {
                //couldn't create sequential guid, fall back on random guid
                return Guid.NewGuid();
            }
        }
    }
}
3
ответ дан 29 November 2019 в 22:43
поделиться

Код C # (безопасный) (Комплименты генератора гребней NHibernate Guid)

Guid GenerateComb()
{
    byte[] destinationArray = Guid.NewGuid().ToByteArray();
    DateTime time = new DateTime(0x76c, 1, 1);
    DateTime now = DateTime.Now;
    TimeSpan span = new TimeSpan(now.Ticks - time.Ticks);
    TimeSpan timeOfDay = now.TimeOfDay;
    byte[] bytes = BitConverter.GetBytes(span.Days);
    byte[] array = BitConverter.GetBytes((long) (timeOfDay.TotalMilliseconds / 3.333333));
    Array.Reverse(bytes);
    Array.Reverse(array);
    Array.Copy(bytes, bytes.Length - 2, destinationArray, destinationArray.Length - 6, 2);
    Array.Copy(array, array.Length - 4, destinationArray, destinationArray.Length - 4, 4);
    return new Guid(destinationArray);
}

Ссылка на источник на github: https: // github .com / nhibernate / nhibernate-core / blob / master / src / NHibernate / Id / GuidCombGenerator.cs

50
ответ дан 29 November 2019 в 22:43
поделиться

@arul, @Doug

Почему вы поместили часть времени в конец GUID?

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

Хорошо, я нашел ответ и этот ответ Бернхарда Кирхера и сайт Сравнение значений GUID и уникальных идентификаторов (ADO.NET) , на который он ссылается .

GUID, сгенерированные таким образом, поэтому не будут работать так же в других базах данных, кроме MS SQL-Server, но это не связано с LINQ-to-SQL.

Извините за искаженные URL-адреса, но у меня недостаточно репутации, чтобы размещать больше ссылок.

2
ответ дан 29 November 2019 в 22:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: