【问题标题】:Linq to sql Repository pattern , Some questionsLinq to sql Repository 模式,一些问题
【发布时间】:2010-04-09 19:37:56
【问题描述】:

我正在使用带有 linq to sql 的存储库模式,我正在为每个表使用一个存储库类。 我想知道,我做得很好/标准吗,

联系存储库

  Contact GetByID()
  Contact GetAll()

CONtactTagRepository

 List<ContactTag> Get(long contactID)
 List<ContactTag> GetAll()
 List<ContactTagDetail> GetAllDetails()

class ContactTagDetail
{
  public Contact Contact {get;set;}
  public ContactTag COntactTag {get;set;}
}

当我需要联系人时,我会调用contactrepository中的方法,对于contacttag也是如此

但是当我需要联系人和标签时,我在 ContactTag 存储库中调用 GetDetais(),它不返回由 orm 生成的 COntactTag 实体,而是返回包含由 orm 生成的 COntact 和 COntactTag 的 ContactTagDetail 实体,我知道我可以简单地调用GetAll 在 COntactTag 存储库中并且可以访问 Contact.ContactTag 但作为它的 linq to sql 它将在查询级别没有延迟加载的选项,所以每当我需要一个具有相关实体的实体时,我都会创建一个投影类

另一个疑问是我真的需要纠正我可以在联系人和 ContactTag 存储库中执行的方法,例如在联系人存储库 GetALlWithTags() 或其他东西中,但我在 COntactTag 存储库中执行此操作

你有什么建议?

【问题讨论】:

    标签: c# linq-to-sql design-patterns


    【解决方案1】:

    我没有时间详细介绍,但表和存储库之间基本上没有一对一的关系。我犯了这个错误,它不起作用。相反,让您的存储库包含概念上相关的所有表。在您的情况下,只需有一个联系人存储库来处理联系人和联系人标签(以及任何其他相关表)。关于“相关”的含义没有任何规定,只有您可以决定 - 但要根据您对应用程序元素如何自然地组合在一起的理解来管理您的决定。

    还可以阅读 SO 上处理类似问题的这两个线程:

    Multiple or Single Repositories with LINQHow to use the repository pattern correctly?

    【讨论】:

    • 它很好,但是当我拥有包含许多相关实体的存储库时,我将在其中编写插入/删除等方法,
    • 您可以将它们全部放在一个存储库中,只要它们作为“工作单元”相关联。
    【解决方案2】:

    这不是存储库模式。存储库模式基本上是创建一个对象,该对象通过(在概念上)充当域中某种类型的所有对象的集合来抽象持久性。

    因此,联系人存储库可能会像这样工作:

    IContacts contacts = GetContactRepository();
    using(var uow = UnitOfWork.Create()) {
      var contact1 = contacts.Get(new FindByNameSpecification("Fred"));
      contact1.LastName = "Rubble";
      var contact2 = new Contact("Barney", "Flistone");
      contacts.Add(contact2);
      // both contact1 and contact 2 are implicitly saved at the end of the unit of work
    }  
    

    对存储库应该如何工作的稍微宽松的定义可能是这样的:

    IContactRepository contacts = GetContactRepository();
    using(var uow = UnitOfWork.Create()) {
      var contact1 = contacts.GetByName("Fred");
      contact1.LastName = "Rubble";
      contacts.Save(contact1);
      var contact2 = new Contact("Barney", "Flistone");
      contacts.Save(contact2);
    }  //The save is explicit but the commit is implicit
    

    你得到的是table data gateway

    问题是您正在为每个表创建一个网关。我建议不要这样做。

    标记是否属于您的联系人域?如果是,那么您应该具有属性

    public class Contact {
      public IEnumerable<Tag> Tags { get; }
      public void TagWith(Tag tag) { .... }
      public void UnTag(Tag tag) { ... }
    }
    

    另外,问问自己,你是否会添加一个标签下的联系人为零?如果没有,那么它会变得更容易 - 您根本不需要网关来管理标签,只需让您的联系人对象处理它

    public interface IContactRepository {
      IEnumerable<Contact> GetAll(); // returns Contacts along with their tags
      void Save(Contact); // saves Contact along with any tags
    } 
    

    顺便说一句,如果标记不是你的域的一部分(因为它是一个应用程序问题)那么你应该有一个单独的服务,甚至可能在一个单独的项目中

    public interface IAssociateTags {
      IEnumerable<Tag> GetTagFor(Contact contact);
      void TagContact(Contact contact, Tag tag);
      void UnTagContact(Contact contact, Tag tag);
    }
    

    【讨论】:

      【解决方案3】:

      我相信你在正确的轨道上。 使用 linq to sql 会遇到的一个问题是与表的一对一映射。所以你不得不暴露多对多的关系表。

      我解决这个问题的方法是使用可以访问 linq to sql 的数据层,但在返回调用之前将所有内容映射回 POCO 对象。

       public IQueryable<ArtGalleryData.Image> GetImagesByImageGroup(int id)
          {
      
              return SqlDataContext.Image_ImageGroups
                  .Where(iig => iig.ImageGroupID == id)
                  .Join(
                  SqlDataContext.Images,
                  iig => iig.ImageID,
                  i => i.ImageID,
                  (iig, i) => new ArtGalleryData.Image 
                  { ImageID = i.ImageID, 
                    Description = i.Description, 
                    Title = i.Title, 
                    Height = i.Height, 
                    Width = i.Width }).AsQueryable();
          }
      

      基本上,我将 linq 对象 Image 映射回 POCO 对象 Image。 (我知道它有点乱,但它是我手头最好的例子。)

      要获得延迟加载的效果,您将返回一个 IQueryable 对象。这将允许您推迟执行查询,直到您需要。

      对于其中具有依赖集合的对象,我发现了这个很好的帮助类:LazyList 它允许通过 IQueryable 延迟加载(延迟执行)集合

      我知道的大部分内容来自阅读 Rob Connerys 博客MVC Store Front

      阅读他的博文并下载 Store front 项目,我认为它会回答您的许多问题。如果您不使用 asp.net MVC,只是查看他的数据访问层应该会有很大帮助。

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 2011-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多