Поддержка специальных типов SQL Server для OrmLite

Я только что узнал о гениальном типе, который упростит мою работу, но похоже, что мой предпочтительный ORM не распознает его.

Есть ли обходной путь, позволяющий ServiceStack OrmLite распознавать HierarchyId в SQL Server? Любые предложения о том, какие файлы нужно изменить и какие намеки, как действовать?

EDIT:

Вот лучшая иллюстрация проблемы. У меня есть следующий класс:

public class MyClass
{
    public int Id { get; set; }
    public SqlHierarchyId HierarchyId { get; set; }
}

SqlHierarchyId - это настраиваемый тип данных SQL Server. OrmLite создаст для него следующий класс:

First MyClass Rendering

Забавно, я могу использовать атрибут [StringLength(255)] в свойстве, и вместо этого он получит тип varchar(255):

Second MyClass Rendering

Я вручную изменил таблицу здесь и добавил тип данных столбца, чтобы продемонстрировать разницу. Обратите внимание на тип данных третьего столбца:

SqlHierarchyId

Наличие представления varchar отлично подходит для других СУБД, поскольку может быть преобразовано в С#, но с SQL Server предпочтительнее, чтобы оно соответствовало соответствующему тип данных. Это упростит создание представлений (благодаря встроенным функциям типа данных HierarchyId).

Я знаю, что тип не поддерживается EF4 (не уверен около 5). Я также просмотрел файл OrmLiteDialectProviderBase.cs на GitHub, и я вижу список поддерживаемых типов данных ADO.NET.

Мой простой вопрос: является ли это сильным ограничением ADO.NET, или это можно увидеть когда-нибудь в OrmLite? Я готов помочь продлить эту часть, если будут сделаны какие-либо предложения.

Ответы

Ответ 1

ADO.NET поддерживает тип иерархии, пример можно найти здесь и показывает, что ADO.NET может считывать значения с Sql Server as иерархия напрямую, но вам нужно передать параметры на сервер в виде строки.

Добавление поддержки методов типа иерархии в структуру ORM приведет к нарушению абстракции между ORM API и RDMS. Я бы предположил, что это причина, по которой такая функциональность не была добавлена ​​в Entity Framework.

Вы можете обойти проблему, сохранив строковое представление иерархии в своей базе данных и имея версию иерархии как вычисленное свойство как в вашей базе данных, так и в вашем классе С#, вам нужно будет исключить вычисленное свойство С# из ORM отображение.

Например, столбец таблицы будет объявлен как:

[SqlHierarchyId] AS ([hierarchyid]::Parse([HierarchyId])) PERSISTED 

и ваш класс:

public class MyClass {

    public string HierarchyId {
        get;
        set;
    }

    [Ignore]
    public SqlHierarchyId SqlHierarchyId {
        get {
            return SqlHierarchyId.Parse(new SqlString(HierarchyId));
        }
        set {
            HierarchyId = value.ToString();
        }
    }

}

Это будет поддерживать обновления с .Net-уровня и позволит вам использовать методы иерархии для построения запросов в SQL Server и работать с материализованными объектами на уровне .Net.

Вам придется создавать запросы против строкового представления в вашем ORM-слое, но это все равно может использовать некоторые вспомогательные методы иерархии, например:

public IEnumerable<MyClass> GetDescendants(MyClass node) {

    string currentLocation = node.HierarchyId;
    string followingSibling 
        = node.SqlHierarchyId.GetAncestor(1)
              .GetDescendant(node.SqlHierarchyId, SqlHierarchyId.Null)
              .ToString();

    return db.Select<MyClass>(n => n.HierarchyId > currentLocation 
                                && n.HierarchyId < followingSibling);

}

Аплодии, если у меня неправильный синтаксис ORMLite.