定义要在控制器中加载哪些数据是一个好习惯吗?

时间:2009-05-17 15:50:52

标签: asp.net-mvc

想象一下,您有一个与其他实体有某种关系的实体,并且您只想加载其中一些实体,以便在不同的视图中显示它们。

例如,给定此实体:

public class Category
{
     public int id;
     public Category child;
     public Category parent;
}

在“ShowChild”视图中,您不想加载“parent”属性,因为您没有显示它。

所以,鉴于这种情况,我在我的存储库中实现了一个非常好的“系统”来从DB中加载实体,只填充我想要的属性。它的工作原理如下:

Category category = repo.FindCategory(id,(int)(LoadLevel.basic | LoadLevel.Child))

所以现在我有一个只加载了id和Child属性的类别实例。

我面临的困境是,如果我在serviceLayer中定义LoadLevel(它应该在哪里),我将不得不在我的服务类中编写两个方法,“LoadCategoryWithChild”和“LoadCategoryWithParent”,每个方法一个查看(DRY违规?)。

public class CategoryService
{
     public Category LoadCategoryWithChild(int id)
     {
         int loadlevel = (int) (LoadLevel.Basic | LoadLevel.Child);
         return repo.FindCategory(id, loadlevel);
     }
}

或者,我看到的另一个选项是在控制器中定义loadlevel(MVC违规?)并在我的服务类中实现一个方法:

public class CategoryService
{
     public Category LoadCategory(int id, int loadlevel)
     {
         return repo.FindCategory(id, loadlevel);
     }
}

哪个选项更好?我认为DRY违规更糟糕,因为它意味着编写了大量冗余代码。

3 个答案:

答案 0 :(得分:1)

我绝对更喜欢第二种解决方案。我不认为控制器给服务类提示它需要什么数据是一个问题(坦率地说,通过调用函数A而不是函数B,它在第一个解决方案中做的是同样的事情)。

我会将第二个参数更改为不是int而且是枚举类型,以便调用者知道有效选项是什么

答案 1 :(得分:0)

这可能是对象关系映射的头号问题。大多数ORM解决方案通过延迟加载对象属性来绕过它,这样您只需要一个满足大多数用例的加载机制。使用其他属性的少数功能可以通过代理请求从View中透明地加载所需的内容。

就我个人而言,我不是上述任何一种解决方案的粉丝,也不是透明代理的第三种解决方案的粉丝。然而,代理解决方案将更加一致地工作,在View层中的微小变化上失败的频率更低,主要影响通常只是一点点性能。当它被证明是一个问题时,你总是可以对它进行优化。

Hibernate作为一个例子使用了这种方法,尽管你必须告诉它属性是否是延迟加载的。在Hibernate中通过代理进行延迟加载也不能在所有情况下延迟加载,因为它需要在事务中。出于实际的性能原因,存在这些限制。在数据库映射方法中,代理/延迟加载是最容易使用的,但它有自己的复杂性。

答案 2 :(得分:0)

我建议:

public Category LoadCategory(int id, params LoadLevel[] levels)
{
    int loadLevel = LoadLevel.Basic;

    foreach (var level in levels)
        loadLevel = loadLevel | level;

    return repo.FindCategory(id, loadlevel);
}

使用示例:

LoadCategory(0, LoadLevel.Parent, LoadLevel.Child); // self + parent+ child
LoadCategory(1, LoadLevel.Child); // self + child
LoadCategory(2); // self only