我刚刚了解了一种天才类型,它可以简化我的大部分工作,但看起来我的首选ORM无法识别它。
是否有一种解决方法让ServiceStack OrmLite识别SQL Server中的HierarchyId
?有关要修改哪些文件以及任何提示如何继续的建议?
编辑:
以下是问题的更好说明。我有以下课程:
public class MyClass
{
public int Id { get; set; }
public SqlHierarchyId HierarchyId { get; set; }
}
SqlHierarchyId是自定义SQL Server数据类型。 OrmLite将为它生成以下类:
有趣的是,我可以使用属性上的[StringLength(255)]
属性,它将获得varchar(255)
类型:
我在这里手动更改了表格并添加了列数据类型以展示差异。请注意第三列的数据类型:
使用varchar
表示与其他DBMS完全一样it can be converted within C#,但对于SQL Server,最好使其与相应的数据类型匹配。这将使视图的创建更容易(由于hierarchyid
数据类型的内置函数)。
我知道EF4不支持这种类型(不确定5)。我还浏览了GitHub上的OrmLiteDialectProviderBase.cs文件,我可以看到支持的ADO.NET数据类型列表。
我的简单问题是:这是ADO.NET的一个强大限制,还是在OrmLite中可以看到这个?如果有任何建议,我愿意帮助扩展这部分。
答案 0 :(得分:1)
ADO.NET支持hierarchyid类型,可以找到一个示例here并显示ADO.NET可以直接从Sql Server读取值作为hierarchyid,但是您需要将参数作为字符串传递给服务器
将对hierarchyid类型方法的支持添加到ORM框架将破坏ORM API和RDMS之间的抽象。我认为这就是没有将这种功能添加到Entity Framework的原因。
您可以通过在数据库中保留层次结构的字符串表示并在您的数据库和C#类中将hierarchyid版本作为计算属性来解决此问题,您需要从ORM中排除计算的C#属性映射。
例如,您的表列将声明为:
[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层的更新,并允许您使用hierarchyid方法在SQL Server中构造查询并使用.Net层中的实体化对象。
您必须在ORM层中构建针对字符串表示的查询,但这仍然可以利用一些hierarchyid帮助方法,例如:
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语法错误,请注意。