C# 使用树状结构中的数据模型实现存储库模式

C# 使用树状结构中的数据模型实现存储库模式,c#,tree,repository-pattern,C#,Tree,Repository Pattern,我有两个不同模型中的两个数据集合,它们实现了一个存储库接口。其中一个在一个平面列表中,它非常适合存储库模型。另一个数据模型的格式是树状结构,我构建的存储库接口的实现看起来非常可疑。我可以尝试将第二个数据模型展平,只使用对父对象的引用,但目前该应用程序有一些很大的好处,因为它能够以树结构的形式获取数据 我想知道的是,是否有人有使用树结构数据模型实现存储库模式的经验。目前,在我的Get(Func谓词)方法中,我使用递归方法将列表展平,并使用LINQ查询返回对象,但我觉得这个实现的成本有点高 任何关于

我有两个不同模型中的两个数据集合,它们实现了一个存储库接口。其中一个在一个平面列表中,它非常适合存储库模型。另一个数据模型的格式是树状结构,我构建的存储库接口的实现看起来非常可疑。我可以尝试将第二个数据模型展平,只使用对父对象的引用,但目前该应用程序有一些很大的好处,因为它能够以树结构的形式获取数据

我想知道的是,是否有人有使用树结构数据模型实现存储库模式的经验。目前,在我的
Get(Func谓词)
方法中,我使用递归方法将列表展平,并使用LINQ查询返回对象,但我觉得这个实现的成本有点高

任何关于如何实现这一点的提示都将不胜感激

下面是get by predicate方法的实现,如果这有助于说明实现的细节的话

protected virtual IEnumerable<T> Get(Func<T, bool> predicate)
{
    var objects = GetAll<T>();
    return objects.Where(predicate);
}
受保护的虚拟IEnumerable Get(Func谓词)
{
var objects=GetAll();
返回对象。Where(谓词);
}
编辑: 还有代码吗

private IEnumerable<TreeData> GetRecursiveObjects(TreeData object)
    {
        var allChildren = new List<TreeData>();
        allChildren.AddRange(object.Children);

        foreach (var child in object.Children)
        {
            allChildren.AddRange(GetRecursiveObjects(child).ToArray());
        }
        return allChildren;
    }

    protected virtual IEnumerable<T> GetAll<T>()
    {
        var objects = new List<T>();
        objects.AddRange(Objects);
        foreach (var object in Objects)
        {
            objects.AddRange(GetRecursiveObjects(object));
        }
        return objects.OfType<T>();
    }
private IEnumerable GetRecursiveObjects(TreeData对象)
{
var allChildren=新列表();
allchildreng.AddRange(object.Children);
foreach(object.Children中的变量child)
{
AddRange(GetRecursiveObjects(child.ToArray());
}
归还所有儿童;
}
受保护的虚拟IEnumerable GetAll()
{
var objects=新列表();
objects.AddRange(对象);
foreach(对象中的变量对象)
{
AddRange(GetRecursiveObjects(object));
}
返回objects.OfType();
}
第二次编辑:

我还对向存储库添加元素的好策略有点困惑。我应该在using代码中处理添加到父元素的子元素,还是存储库应该将元素和引用都带到它的父元素并处理整个添加操作

tl;博士


尝试用树状结构的数据实现存储库接口是否疯狂

您可以编写一个方法,使用迭代器块(
yield return
)遍历树并返回一个
IEnumerable

这样,您就不必创建树内容的“平面”集合,只需使用LINQ to对象来应用谓词:

protected virtual IEnumerable<T> Get(Func<T, bool> predicate)
{
  return WalkAll().Where( predicate );
}
受保护的虚拟IEnumerable Get(Func谓词)
{
返回WalkAll()。其中(谓词);
}

事实上,在客户端代码枚举LINQ查询之前,LINQ查询甚至不会被计算。

问题的答案实际上取决于树的结构以及实际查找数据的方式。你能提供一点更详细的信息吗?GetAll方法递归地遍历子对象并将它们添加到列表中。只是出于好奇:为什么你坚持要将结构扁平化?为什么存储库不能/不应该返回树状结构?我希望IRepository的用户在获取所有项目时始终获取IEnumerable。如果我为这个GetAll方法实现了一个特例,那么我将无法为另一个平坦的数据结构使用相同的接口。