Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Server specific types support for OrmLite

I just learned about a genius type that would simplify a lot of my work but it looks like my preferred ORM does not recognize it.

Is there a workaround to let ServiceStack OrmLite recognize HierarchyId in SQL Server? Any suggestions about which files to modify and any hints how to proceed?

EDIT :

Here is a better illustration of the problem. I have the following class:

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

SqlHierarchyId is a custom SQL Server data type. OrmLite will generate the following class for it:

First MyClass Rendering

Funny enough, I can use the [StringLength(255)] attribute on the property and it will get the varchar(255) type instead:

Second MyClass Rendering

I manually changed the table here and added the column data type to showcase the difference. Please note the data type of the third column:

SqlHierarchyId

Having a varchar representation is perfectly fine with other DBMS as it can be converted within C#, but with SQL Server it is preferable to have it match the corresponding data type. This will make the creation of views easier (due to the built-in functions of the hierarchyid data type).

I know the type is not supported by EF4 (not sure about 5). I also browsed the OrmLiteDialectProviderBase.cs file on GitHub and I can see a list of supported ADO.NET data types.

My simple question is: Is this a strong limitation by ADO.NET or this can be seen sometime in OrmLite? I am willing to help extending this part if any suggestions are made.

like image 674
Moslem Ben Dhaou Avatar asked Feb 17 '13 17:02

Moslem Ben Dhaou


People also ask

What is OrmLite C#?

As its GitHub page says, OrmLite is a set of lightweight C# extension methods around System. Data. * interfaces which is designed to persist POCO classes with a minimal amount of intrusion and configuration.

Can I use SQL in Mobile?

Similarly, there are apps you can download on your phone (both on iOS and Android) where you can connect to a database hosted somewhere online so you can run SQL queries on. Again, this isn't a database installed locally on the phone, but you're making an internet connection to a database somewhere.

Is SQL available for Android?

SQL Android allows you to manage multiple independent databases for each application, update or synchronize them from device and even access them from the file system.


1 Answers

ADO.NET has support for the hierarchyid type, an example can be found here and shows ADO.NET can read values from Sql Server as a hierarchyid directly but you need to pass parameters to the server as a string.

Adding support for the hierarchyid type methods to a ORM framework would break the abstraction between the ORM API and the RDMS. I would assume this is the reason such functionality has not been added to Entity Framework.

You could work around the issue by keeping a string representation of the hierarchy in your database and having the hierarchyid version as a computed property in both your database and your C# class, you would need to exclude the computed C# property from the ORM mapping.

For example your table column would be declared as:

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

and your class as:

public class MyClass {

    public string HierarchyId {
        get;
        set;
    }

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

}

This will persisted updates from the .Net layer and allow you to use the hierarchyid methods to construct queries in SQL Server and work with materialised objects in the .Net layer.

You would have to construct queries against the string representation in you ORM layer but this could still leverage some of the hierarchyid helper methods, for example:

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);

}

Aplogies if I have got the ORMLite syntax wrong.

like image 182
Dave Manning Avatar answered Nov 03 '22 07:11

Dave Manning