2011-12-08 53 views
4

在阅读ASP.NET MVC 3.0项目中的Repository Design模式后,我遇到了一个让我困惑的问题,并开始质疑模式的好处。也许有人可以帮我澄清这一点。存储库模式:好还是坏?

我有以下3个表:

  • - 用户parent
  • - UserLeadchild of User
  • - UserLeadNoteschild of UserLead

粗略地说,表和它们之间的关系是这样设计的:

  • 用户[ID]
  • UserLead[ID,用户ID(外键)
  • UserLeadNotes[Id,UserLeadId(外键)]

我有一个BaseRepository,其中包含基本的CRUD方法。 (IEnumerable<TEntity> Get(), TEntity GetByID(), Insert(), Delete(), etc…)

随着到位,我也有一个Service Layer如果在需要的时候并调用适当的存储库。

简而言之,应用程序显示一个UserLead并允许用户添加/删除该UserLead的注释(在UserLeadNotes表中存储/删除)。添加/删除笔记通过Ajax调用完成。注释的删除沿着我希望删除的注释的“id”传递。

现在...之前,我确实删除的笔记,我需要确保的音符真正属于自己的登录用户当前(User.Identity.Name aka UserId

考虑我的方法deleteUserNote(int noteId)只接收一个“noteId”参数考虑我UserLeadNotes表UserId外键,我需要做的,就是增加一个

。包括(“UserLead')

_userLeadNoteRepository里面有类似:

UserLeadNote userLeadNote = _userLeadNoteRepository 
       .AllIncluding(p => p.UserLead) 
       .FirstOrDefault(p => p.UserLeadNoteID.Equals(noteId) 
        && p.UserLead.UserID.Equals(User.Identity.Name)); 

那我就删,我只是找到了UserLeadNote对象:

_userLeadNoteRepository.Delete(userLeadNote); 

问题:

按照上面的方法,这将迫使我为我的UserLeadNotes创建一个存储库,b)由于.Include()找到的userLeadNote对象将具有一个名为UserLead的属性,其中包含UserLead表中定义的所有字段。

如果我的UserLead表碰巧有14个字段,其中的10个字段是ntext,这意味着我将会加载/保存太多的信息!

如果我是使用,而不是Lambda表达式的,一个LINQ声明绕过库并直接使用我的上下文:

using(MyContext db = new MyContext()) 
      { 
       var query = 
        from uln in db.UserLeadNote 
        join ul in db.UserLead on uln.UserLeadID equals ul.UserLeadID 
        where uln.UserLeadNoteID == userLeadNoteID 
         && ul.UserID == User.Identity.Name 
        select uln; 

       var userLeadNote = query.FirstOrDefault(); 

       db.UserLeadNote.Remove(userLeadNote); 

       db.SaveChanges(); 
      } 

难道这种做法是因为它会没有更有效从UserLead表中带回这些不必要的字段? (例如那10个字段)。

除非我没有正确使用存储库模式,或者这可能是一个实体框架问题,否则我想知道任何人的想法!

请记住,我知道有一个存储库模式的好处,但好奇,如果这是人们有或没有的某种问题。如果是这样,他们是否决定放弃模式,并使用Linq语句直接使用它们的上下文。

两个邪恶中最小的是什么?

+3

我在一些项目上使用了该模式,但放弃了它,直接转向上下文。如果你继续使用模式,你应该阅读** Aggregate Roots **。你不需要为每个表/实体回购,只是你的核心部分。我通常为复杂的业务逻辑/关系保留完整的DDD。 http://devlicio.us/blogs/casey/archive/2009/02/16/ddd-aggregates-and-aggregate-roots.aspx – Ryan

+0

我现在更明白我的UserLead和UserLeadNotes表将被视为一个聚合。所以我的UserLead表将被视为聚合根。这意味着我应该只有一个针对该聚合根表的存储库,并从该根目录导航到我的子项。考虑到这一点,如何使我的单个UserLead存储库允许我导航到我的孩子并获得FirstOrDefault()子对象而不加载父代的附加字段?也许你是对的;我应该删除存储库模式,并直接从我的服务层调用/使用我的上下文 – Vlince

回答

2

总之,

阅读瑞安的后鲁昂的帖子,似乎创建一个每个实体的存储库可能不是合适的方法。如果我有一个孩子(或孩子的孩子)实体,我应该创建一个单独的父库,并通过孩子(或孩子的孩子)导航我的方式。

我遇到的问题是,当试图删除一个子实体(没有父母的外键)的孩子时,我不得不.Include(“”)其他“上”表。 (在我的情况中,只有一张桌子,父母,但可以很容易地删除一个孩子的孩子的孩子,并将不得不Include()许多“父母/上”表)。

最后,包括Parent表创建了一个属性,该属性包含Parent的所有字段,在我的情况下,这被认为是“获取”了我手头简单任务的太多信息。

这个所谓的问题,可以避免,如果我要放弃使用仓库模式,而是直接使用上下文。

对于某些人来说,这可能不是问题(或者他们根本不知道发生了什么),对于其他人来说,使用Pattern更重要。

我还没有决定完全删除存储库模式,因为我喜欢它带来的表。

感谢所有。

+1

很高兴我能帮到你。真正让我想起我过度使用存储库模式的是Ayende博客上的一系列帖子。 http://ayende.com/blog/tags/design开始阅读“罪恶的工资”,然后可能连续12个帖子(读下页面)是绝对的黄金。 – Ryan

+0

@Vincen因为有多个包含调用,我的“我手头的简单任务的信息太多了”。思考存储库,但不知道:http://stackoverflow.com/questions/17529796/what-is-the-best-practice-for-multiple-include-method-calls-in-entity-framework –

1

尝试看看这里:

asp.net mvc page is not showing properties from associated objects

有我的回答有关于这种通用仓库模式被滥用的解释/意见

+0

感谢您的职位!所以最后,就像Ryan的评论中提到的那样,我应该放弃Repository Pattern并直接使用我的Context将我的查询直接合并到我的服务层。这将提高性能,并返回我正是我想要的,没有额外的数据/字段。在减少模式方面的折中是,现在我的服务层将与我的数据库紧密耦合。哦,只要我知道这一点。谢谢 – Vlince

相关问题