是Kigg MVC应用干?我们可以调整存储库 [英] Is Kigg MVC application DRY? Can we tweak the Repository
问题描述
我最近正在看一下卡子门祖尔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屋!