Существует ли практический способ использования типа данных hierarchyID в инфраструктуре сущностей 4?

В настоящее время CLR UDT, включая HierarchyID, не поддерживаются в Entity Framework 4. HierarchyID.ToString() полезен, но разбивается, как только у любого элемента есть 10+ братьев и сестер (основная структура - это 3/4/12/или/3/4/2/, поэтому 12-й node будет сортировать до 2-го node).

Немного больше о возможных вариантах:

  • Верните иерархический идентификатор в качестве varbinary и реализуйте мой собственный двоичный сортировщик

  • Верните иерархический идентификатор в качестве varbinary и реализуйте мой собственный метод hierarchyID.ToString(), который заполняет цифры нулями при построении строки, чтобы результирующая строка была сортируемой (например, "0004 0004/0012/" ), Я разобрал Microsoft.SqlServer.Types.dll и посмотрел на реализацию. Похоже, что интеркалы основаны на классе под названием "OrdTree", и я мог бы использовать этот класс в качестве основы для повторной реализации.

  • Напишите мой собственный тип CLR для SQL для работы с двоичными данными и создания собственной строки (вариант варианта 2). Хотя, поставляется с добавленной головной болью развертывания.

  • Напишите SQL udf для синтаксического анализа строки иерархии и поместите ее на уровень БД. Отсутствие обработки массивов /regex кажется самой большой проблемой здесь.

  • Сортировка по иерархииID на уровне базы данных и использование функции ROW_NUMBER() в качестве подставки для порядка сортировки.

  • Напишите некоторые вспомогательные методы на .net-слое, которые повторно анализируют иерархиюId.ToString() и создают сортируемую строку (например, "/0003/0004/0012/" ).

Итак, мой вопрос: кто-нибудь работал над ограничением? Использовали ли вы какие-либо из вышеперечисленных стратегий? Если да, то как?

Ответы

Ответ 1

Ну, я, кажется, получаю мнения, но никаких ответов. У меня возникли некоторые непосредственные потребности в работе с иерархической структурой над SQL, поэтому я собрал статический вспомогательный класс. Я не считаю это полным решением, но пока он работает относительно хорошо. PadPath - действительно критическая функция здесь.

public static class SQLHierarchyManipulatin {
    const int   DEFAULT_PAD_LEN     = 3;
    const char  DEFAULT_PAD_CHAR    = '0';

    public static string PadPath(string Hierarchy) {
        return PadPath (Hierarchy, DEFAULT_PAD_LEN);
    }       
    public static string PadPath(string Hierarchy, int padLen) {
        string[]    components  = Hierarchy.Split('/');

        for (var i = 0; i < components.Length; i++ ) {
            if (components[i] != "") {
                components[i] = components[i].PadLeft(padLen, DEFAULT_PAD_CHAR);
            }
        }
        return string.Join("/", components);
    }

    public static int CurrentNodeIndex(string Hierarchy) {
        string[]    components  = Hierarchy.Split('/');
        string      startItem   = components[components.Length - 2]; //one slot back from trailing slash

        return int.Parse(startItem);
    }

    public static string ParentPath (string Hierarchy) {
        return  Hierarchy.Substring(0, Hierarchy.TrimEnd('/').LastIndexOf('/') + 1);
    }

    public static string AppendChildWithPadding (string Hierarchy, int childIndex, int padLen) {
        return AppendChild(Hierarchy, childIndex, DEFAULT_PAD_LEN);
    }
    public static string AppendChildWithPadding (string Hierarchy, int childIndex) {
        return AppendChild(Hierarchy, childIndex, DEFAULT_PAD_LEN);
    }
    public static string AppendChild (string Hierarchy, int childIndex) {
        return AppendChild(Hierarchy, childIndex, DEFAULT_PAD_LEN);
    }
    public static string AppendChild (string Hierarchy, int childIndex, int padLen) {
        return Hierarchy + childIndex.ToString().PadLeft(padLen, DEFAULT_PAD_CHAR) + "/";
    }
}

Надеюсь, это поможет кому-то! Хотя, мне все равно хотелось бы услышать от людей.