Linq 中的分层数据 - 选项和性能
我有一些分层数据 - 每个条目都有一个 id 和一个(可为空)父条目 id。 我想检索树中给定条目下的所有条目。 这是在 SQL Server 2005 数据库中。 我正在 C# 3.5 中使用 LINQ to SQL 查询它。
LINQ to SQL 不直接支持公用表表达式。 我的选择是使用多个 LINQ 查询在代码中组装数据,或者在数据库上创建显示 CTE 的视图。
当数据量变大时,您认为哪个选项(或另一个选项)会表现更好? Linq to SQL 是否支持 SQL Server 2008 的 HierarchyId 类型?
I have some hierarchical data - each entry has an id and a (nullable) parent entry id.
I want to retrieve all entries in the tree under a given entry. This is in a SQL Server 2005 database. I am querying it with LINQ to SQL in C# 3.5.
LINQ to SQL does not support Common Table Expressions directly. My choices are to assemble the data in code with several LINQ queries, or to make a view on the database that surfaces a CTE.
Which option (or another option) do you think will perform better when data volumes get large?
Is SQL Server 2008's HierarchyId type supported in Linq to SQL?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这个选项也可能有用:
LINQ AsHierarchy() 扩展方法< /强>
http://www.scip.be/index.php?Page=ArticlesNET18
This option might also prove useful:
LINQ AsHierarchy() extension method
http://www.scip.be/index.php?Page=ArticlesNET18
我很惊讶没有人提到替代数据库设计 - 当层次结构需要从多个级别展平并以高性能检索时(考虑存储空间则不然),最好使用另一个实体-2-实体表来跟踪层次结构而不是parent_id方法。
它不仅允许单亲关系,还允许多亲关系、级别指示和不同类型的关系:
I am surprised nobody has mentioned an alternative database design - when hierarchy needs to be flattened from multiple levels and retrieved with high performance (not so considering storage space) it is better to use another entity-2-entity table to track hierarchy instead of parent_id approach.
It will allow not only single parent relations but also multi parent relations, level indications and different types of relationships:
我将根据 CTE 设置一个视图和一个关联的基于表的函数。 我的理由是,虽然您可以在应用程序端实现逻辑,但这将涉及通过线路发送中间数据以在应用程序中进行计算。 使用 DBML 设计器,视图可转换为表实体。 然后,您可以将该函数与 Table 实体相关联,并调用在 DataContext 上创建的方法来派生视图定义的类型的对象。 使用基于表的函数允许查询引擎在构造结果集时考虑您的参数,而不是在事后对视图定义的结果集应用条件。
要使用它,你会做类似的事情 - 假设一些合理的命名方案:
I would set up a view and an associated table-based function based on the CTE. My reasoning for this is that, while you could implement the logic on the application side, this would involve sending the intermediate data over the wire for computation in the application. Using the DBML designer, the view translates into a Table entity. You can then associate the function with the Table entity and invoke the method created on the DataContext to derive objects of the type defined by the view. Using the table-based function allows the query engine to take your parameters into account while constructing the result set rather than applying a condition on the result set defined by the view after the fact.
To use it you would do something like -- assuming some reasonable naming scheme:
我通过两种方式完成此操作:
I have done this two ways:
可以修改此扩展方法以使用 IQueryable。 我过去曾在一系列对象上成功使用过它。 它可能适用于您的场景。
我是这样称呼它的:
此代码是发现的代码的改进、错误修复版本 此处。
This extension method could potentially be modified to use IQueryable. I've used it succesfully in the past on a collection of objects. It may work for your scenario.
Here is how I called it:
This code is an improved, bug-fixed version of the code found here.
在 MS SQL 2008 中,您可以直接使用 HierarchyID ,在 sql2005 中,您可以必须手动实施它们。 ParentID 在大型数据集上的性能不佳。 另请参阅本文以获取有关该主题的更多讨论。
In MS SQL 2008 you could use HierarchyID directly, in sql2005 you may have to implement them manually. ParentID is not that performant on large data sets. Also check this article for more discussion on the topic.
我从 Rob Conery 的博客 中得到了这种方法(在第 6 部分查看此代码,也在 codeplex 上),我喜欢使用它。 可以对其进行改造以支持多个“子”级别。
I got this approach from Rob Conery's blog (check around Pt. 6 for this code, also on codeplex) and I love using it. This could be refashioned to support multiple "sub" levels.
从客户端获取数据的麻烦在于您永远无法确定需要深入多深。 此方法将为每个深度执行一次往返,并且可以联合起来在一次往返中执行从 0 到指定深度的操作。
然而,它不能实现任意深度。 如果您确实需要任意深度,则需要在数据库中执行此操作 - 这样您就可以做出正确的停止决定。
The trouble with fetching the data from the client side is that you can never be sure how deep you need to go. This method will do one roundtrip per depth and it could be union'd to do from 0 to a specified depth in one roundtrip.
It can't, however, do arbitrary depth. If you really do require arbitrary depth, you need to do that in the database - so you can make the correct decision to stop.
请阅读以下链接。
http://support.microsoft.com/default.aspx? scid=kb;en-us;q248915
Please read the following link.
http://support.microsoft.com/default.aspx?scid=kb;en-us;q248915