如何改造Entity Framework模型,实现多层级层级的通用化编程?
这种嵌套层级的重复代码确实让人头大——每次加新层级都要复制粘贴一堆排序逻辑,维护起来简直噩梦。好在我们可以利用EF模型的继承特性和面向接口编程来彻底解决这个问题,让代码变得通用且易于维护。
问题分析
你现在的模型是一个多层级的树形结构:
- TblProject
- TblLine
- TblGroup
- TblStation
- TblDevice
- TblSubDevice
- TblSubSubDevice
- TblSubDevice
- TblDevice
- TblStation
- TblGroup
- TblLine
所有实体都继承自BaseTable(包含ID、Name、Type属性),但每个实体的子集合属性名称不同(比如tblLines、tblGroups),导致你不得不为每个层级写重复的排序逻辑。
解决方案:用接口统一树形节点行为
核心思路是给所有层级的实体定义一个通用接口,让它们都能暴露自己的子节点集合,然后写一个递归的通用排序方法,一次性处理所有层级。
1. 定义层级节点接口
先创建一个接口,用来统一获取子节点的方式:
using System.Collections.Generic; public interface IHierarchicalNode { // 返回当前节点的所有子节点(转换为BaseTable类型) IEnumerable<BaseTable> GetChildNodes(); }
2. 修改EF实体实现接口
让每个实体类都实现这个接口,返回对应的子集合:
// TblProject示例 public class TblProject : BaseTable, IHierarchicalNode { // 原EF导航属性 public virtual ObservableCollection<TblLine> tblLines { get; set; } public IEnumerable<BaseTable> GetChildNodes() { // 将子集合转换为BaseTable类型 return tblLines.Cast<BaseTable>(); } } // TblLine示例 public class TblLine : BaseTable, IHierarchicalNode { public virtual ObservableCollection<TblGroup> tblGroups { get; set; } public IEnumerable<BaseTable> GetChildNodes() { return tblGroups.Cast<BaseTable>(); } } // 以此类推,给TblGroup、TblStation、TblDevice、TblSubDevice、TblSubSubDevice都实现这个接口
3. 编写通用递归排序方法
现在可以写一个通用方法,递归遍历所有层级并排序:
using System.ComponentModel; using System.Collections.Generic; using System.Linq; public static class HierarchicalTreeHelper { public static void OrderHierarchicalTree(IEnumerable<BaseTable> rootNodes, ListSortDirection direction) { foreach (var node in rootNodes) { // 如果当前节点是层级节点,处理它的子集合 if (node is IHierarchicalNode hierarchicalNode) { var childNodes = hierarchicalNode.GetChildNodes(); // 处理子集合的排序(针对ObservableCollection的视图) if (childNodes is ObservableCollection<BaseTable> childCollection) { var view = CollectionViewSource.GetDefaultView(childCollection); view.SortDescriptions.Clear(); view.SortDescriptions.Add(new SortDescription("Name", direction)); } // 递归处理子节点的子节点 OrderHierarchicalTree(childNodes, direction); } } } }
4. 调用通用方法
现在排序整个树形结构只需要一行代码:
// 假设你的根节点集合是ObservableCollection<TblProject> projects HierarchicalTreeHelper.OrderHierarchicalTree(projects, ListSortDirection.Ascending);
额外优化
- 如果以后新增新的层级节点(比如TblSubSubSubDevice),只需要让它实现
IHierarchicalNode接口,排序方法完全不需要修改。 - 如果你的导航属性不是
ObservableCollection,可以调整GetChildNodes的返回逻辑,确保返回正确的子节点集合。 - 还可以扩展这个通用方法,支持按
Type或者其他BaseTable属性排序,只需要把排序属性名作为参数传入即可。
内容的提问来源于stack exchange,提问作者PigSpider
相关产品推荐
相关产品推荐

