是Kigg MVC应用干?我们可以调整存储库 [英] Is Kigg MVC application DRY? Can we tweak the Repository

查看:128
本文介绍了是Kigg MVC应用干?我们可以调整存储库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近正在看一下卡子门祖尔Kigg MVC实现(卡子岩石),并注意到一些code,似乎击败DRY / SOC原则。我很想得到大家的一个可能的重构想法分离关注。

I was recently taking a look at the Kazi Manzur Kigg MVC implementation (Kazi rocks) and noticed some code that seemed to defeat the DRY/SOC principle. I'd love to have everyone's thoughts on a possible refactor to separate concerns.

Kigg同时实现了一个添加每个仓储类(删除方法注意 BaseRepository 比可以由每个具体的实现重载虚拟方法)

Kigg implements both an Add and Remove method on each repository class ( Note: BaseRepository has virtual methods than can be overloaded by each concrete implementation.)

Kigg.Repository.LinqToSql.CategoryRepository Kigg.Repository.LinqToSql.StoryRepository 两者的实现级联通过他们的删除方法,以删除子实体删除。 (注意:类别有一个父的关系(一到多),以故事,所以他们上下贯通的对象图分享故事一样子关系)<一个href=\"http://weblogs.asp.net/rashid/archive/2009/02/12/domain-model-developing-kigg-v2-0-part-1.aspx\"相对=nofollow>见图表。违规code是两个库中删除每个人的子实体方式:

The implementations for the Kigg.Repository.LinqToSql.CategoryRepository and the Kigg.Repository.LinqToSql.StoryRepository both cascade deletes via their Remove methods in order to delete child entities. ( Note: Category has a parent relationship (one-to-many) to Story, so they share the same child relationships from Story down through the object graph) see diagram . The offending code is the way both repositories delete each others child entities:

CategoryRepository

CategoryRepository

namespace Kigg.Repository.LinqToSql.CategoryRepository{
    //using statements omitted
    public class CategoryRepository : BaseRepository<ICategory, Category>, ICategoryRepository
    {
    //code omitted

    public override void Remove(ICategory entity)
    {
        Check.Argument.IsNotNull(entity, "entity");

        Category category = (Category) entity;

        Database.DeleteAll(Database.StoryViewDataSource.Where(v => v.Story.CategoryId == category.Id));
        Database.DeleteAll(Database.CommentSubscribtionDataSource.Where(cs => cs.Story.CategoryId == category.Id));
        Database.DeleteAll(Database.CommentDataSource.Where(c => c.Story.CategoryId == category.Id));
        Database.DeleteAll(Database.VoteDataSource.Where(v => v.Story.CategoryId == category.Id));
        Database.DeleteAll(Database.MarkAsSpamDataSource.Where(sp => sp.Story.CategoryId == category.Id));
        Database.DeleteAll(Database.StoryTagDataSource.Where(st => st.Story.CategoryId == category.Id));
        Database.DeleteAll(Database.StoryDataSource.Where(s => s.CategoryId == category.Id));

        base.Remove(category);
    }
}
}

StoryRepository

StoryRepository

namespace Kigg.Repository.LinqToSql
{

    //using statements omitted


    public class StoryRepository : BaseRepository<IStory, Story>, IStoryRepository
    {

    //code omitted


    public override void Remove(IStory entity)
    {
        Check.Argument.IsNotNull(entity, "entity");

        Story story = (Story) entity;

        Database.DeleteAll(Database.StoryViewDataSource.Where(sv => sv.StoryId == story.Id));
        Database.DeleteAll(Database.CommentSubscribtionDataSource.Where(cs => cs.StoryId == story.Id));
        Database.DeleteAll(Database.CommentDataSource.Where(c => c.StoryId == story.Id));
        Database.DeleteAll(Database.VoteDataSource.Where(v => v.StoryId == story.Id));
        Database.DeleteAll(Database.MarkAsSpamDataSource.Where(sp => sp.StoryId == story.Id));
        Database.DeleteAll(Database.StoryTagDataSource.Where(st => st.StoryId == story.Id));

        base.Remove(story);
    }
    }

}

我会假设一个更好的设计本来是正确的 CategoryRepository 调用上删除方法 StoryRepository ,从而为委托故事的子对象清除到 StoryRepository 它所属的关注?从维修点的视图任何补充故事的孩子都需要 DeleteAll 调用被添加到这两个 CategoryRepository StoryRepository

Would I be correct in assuming that a better design would have the CategoryRepository calling the Remove method on the StoryRepository, thereby delegating the concern for the Story's child object removal to the StoryRepository where it belongs? From a maintenance point-of-view any additions to the Story's children would require DeleteAll calls to be added to both the CategoryRepository and the StoryRepository.

什么会是一个更好的实施?

What would be a better implementation?

该不该 CategoryRepository 被重构到 StoryRepository 直接使用?:
CategoryRepository(重构)

Should the CategoryRepository be refactored to use the StoryRepository directly?: CategoryRepository (refactor)

namespace Kigg.Repository.LinqToSql.CategoryRepository{
    //using statements omitted
    public class CategoryRepository : BaseRepository<ICategory, Category>, ICategoryRepository
    {
    //code omitted

    public override void Remove(ICategory entity)
    {
        Check.Argument.IsNotNull(entity, "entity");

        Category category = (Category) entity;

        // refactor - start
        StoryRepository _storyRepository = new StoryRepository( Database );
        category.Stories.ForEach( story => _storyRepository.Remove( story ) );
        // refactor - end

        base.Remove(category);
    }
}
}

这个重构将允许 CategoryRepository 来重用在 StoryRepository ,也应该重复使用相同的LinqToSql拆除逻辑的DataContext 由给予 StoryRepository 数据库参数引用>构造函数。但是,当涉及到单元测试它开始有臭味。

This refactor would allow the CategoryRepository to reuse the removal logic in the StoryRepository and should also reuse the same LinqToSql DataContext that is referenced by the Database argument given to the StoryRepository constructor. But when it comes to unit testing it starts to have an odor.

会更好的重构包括使用IOC(Kigg使用统一作为IOC容器)注入 PerWebRequest 范围的实例 IStoryRepository CategoryRepository 的构造?

Would a better refactor include using IoC (Kigg uses Unity as its Ioc container) to inject the PerWebRequest scoped instance of IStoryRepository into the CategoryRepository's constructor?

CategoryRepository(重构坐2)

CategoryRepository (refactor take 2)

namespace Kigg.Repository.LinqToSql.CategoryRepository{
    //using statements omitted
    public class CategoryRepository : BaseRepository<ICategory, Category>, ICategoryRepository
    {


    private readonly IStoryRepository _storyRepository;

    public CategoryRepository(IDatabase database, IStoryRepository storyRepository) : base(database)
    {
        Check.Argument.IsNotNull(storyRepository, "storyRepository");
        _storyRepository = storyRepository;
    }

    public CategoryRepository(IDatabaseFactory factory, IStoryRepository storyRepository) : base(factory)
    {
        Check.Argument.IsNotNull(storyRepository, "storyRepository");
        _storyRepository = storyRepository;
    }

    //code omitted

    public override void Remove(ICategory entity)
    {
        {
        Check.Argument.IsNotNull(entity, "entity");

        Category category = (Category) entity;

        // refactor - start
        category.Stories.ForEach( story => _storyRepository.Remove( story ) );
        // refactor - end

        base.Remove(category);
    }
}
}

通过本次重构,我们现在可以在单元测试,并通过统一的Ioc注入 CategoryRepository IStoryRepository 的一个实例。当然,我们将不得不重构这个延伸到每一个repository类,因此他们可能倾向于自己的孩子的responsibilites。

With this second refactor we can now inject an instance of IStoryRepository into CategoryRepository during unit testing and via Unity Ioc. Of course we would have to extend this refactor to each repository class so they could tend to their own children's responsibilites.

什么是每个人的想法?

推荐答案

JBland,如在数据库中定义LingToSql将处理级联。虽然SQL Server不允许多个级联路径的。

JBland, LingToSql will handle cascades as defined in the database. Although, SQL Server does not allow multiple cascade paths.

该Kigg数据库没有级联删除或更新规则来定义,但如果存储库实现执行必要删除它们是不需要的。

The Kigg database doesn't have cascading Delete or Update rules defined, but they aren't needed if the repository implementation performs the necessary deletes.

这篇关于是Kigg MVC应用干?我们可以调整存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆