簡體   English   中英

Kigg MVC應用程序DRY? 我們可以調整存儲庫嗎?

[英]Is Kigg MVC application DRY? Can we tweak the Repository

我最近看了Kazi Manzur Kigg MVC實現(Kazi rocks),並注意到一些代碼似乎打敗了DRY / SOC原理。 我希望每個人都能想到可能的重構問題。

Kigg在每個存儲庫類上實現了AddRemove方法( 注意BaseRepository具有虛擬方法,而不是每個具體實現都可以重載。)

Kigg.Repository.LinqToSql.CategoryRepositoryKigg.Repository.LinqToSql.StoryRepository都通過其Remove方法級聯刪除,以便刪除子實體。 注意 :類別與Story具有父關系(一對多),因此它們從Story向下通過對象圖共享相同的子關系) 請參見圖表 違規代碼是兩個存儲庫刪除彼此子實體的方式:

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

 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); } } } 

假設更好的設計讓CategoryRepositoryStoryRepository上調用Remove方法,從而將Story的子對象刪除的關注委托給它所屬的StoryRepository ,我是否正確? 從維護的角度來看,對Story的子項的任何添加都需要將DeleteAll調用添加到CategoryRepositoryStoryRepository

什么是更好的實施?

應該重構CategoryRepository以直接使用StoryRepository嗎?: 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的刪除邏輯,並且還應該重用與StoryRepository構造函數提供的Database參數相同的LinqToSql DataContext 但是當談到單元測試時,它開始有氣味。

會更好的重構包括使用IOC(Kigg使用統一作為IOC容器)的注入PerWebRequest的范圍的情況下IStoryRepositoryCategoryRepository的構造?

CategoryRepository(重構取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); } } } 

有了這個第二個重構,我們現在可以在單元測試期間通過Unity Ioc將一個IStoryRepository實例注入到CategoryRepository中。 當然,我們必須將這個重構擴展到每個存儲庫類,以便他們可以傾向於自己孩子的責任。

每個人的想法是什么?

請原諒我對L2S的無知(我使用NHibernate),但是它不能自動處理級聯嗎?

JBland,LingToSql將處理數據庫中定義的級聯。 雖然,SQL Server不允許多個級聯路徑

Kigg數據庫沒有定義級聯的刪除或更新規則,但如果存儲庫實現執行必要的刪除,則不需要它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM