Sql 特设数据和存储库模式

Sql 特设数据和存储库模式,sql,database,model,repository-pattern,Sql,Database,Model,Repository Pattern,从存储库返回不适合任何模型实体或扩展了某些模型实体的即席(定制的逐案)数据的推荐方法是什么 101个例子是无处不在的hello word应用程序:博客系统。假设您想加载一个post列表,其中post条目包含post实体中不存在的一些附加信息。假设它是评论的数量以及最后一条评论的日期和时间。如果使用普通的旧SQL并直接从数据库读取数据,那么这将是非常简单的。如果我负担不起为每篇文章加载整个评论集,并且我想在一个数据库中完成,那么我应该如何使用存储库模式以最佳方式完成这项工作?对于这种情况,有什么常

从存储库返回不适合任何模型实体或扩展了某些模型实体的即席(定制的逐案)数据的推荐方法是什么

101个例子是无处不在的hello word应用程序:博客系统。假设您想加载一个post列表,其中post条目包含post实体中不存在的一些附加信息。假设它是评论的数量以及最后一条评论的日期和时间。如果使用普通的旧SQL并直接从数据库读取数据,那么这将是非常简单的。如果我负担不起为每篇文章加载整个评论集,并且我想在一个数据库中完成,那么我应该如何使用存储库模式以最佳方式完成这项工作?对于这种情况,有什么常用的模式吗?现在假设您有一个中等复杂的web应用程序,其中每个页面都需要稍微不同的自定义数据,并且无法加载完整的层次结构(性能、内存需求等)

一些随意的想法:

  • 向每个模型添加可由自定义数据填充的属性列表

  • 子类逐个为实体建模,并为每个子类创建自定义读取器

  • 使用LINQ、编写特殊查询和读取匿名类

  • 注意:我问了一个问题,但它似乎太笼统了,没有引起太多的注意

    示例:

    根据下面答案中的建议,我添加了一个更具体的示例。以下是我试图描述的情况:

    IEnumarable<Post> posts = repository.GetPostsByPage(1);
    foreach (Post post in posts)
    {
    
        // snip: push post title, content, etc. to view
    
        // determine the post count and latest comment date
        int commentCount = post.Comments.Count();
        DateTime newestCommentDate = post.Comments.Max(c => c.Date);
    
        // snip: push the count and date to view
    
    }
    
    IEnumarable posts=repository.GetPostsByPage(1);
    foreach(以职位为单位的职位)
    {
    //剪贴:将文章标题、内容等推送到视图
    //确定帖子数量和最新评论日期
    int commentCount=post.Comments.Count();
    DateTime newestCommentDate=post.Comments.Max(c=>c.Date);
    //snip:按下计数和日期以查看
    }
    
    如果我不做任何额外的事情并使用现成的ORM,这将导致n+1个查询,或者可能是一个查询加载所有帖子和评论。但最理想的情况是,我希望能够只执行一个SQL,它将为每个帖子返回一行,包括帖子标题、正文等,以及同一个帖子中的评论计数和最近的评论日期。这在SQL中是微不足道的。问题是,我的存储库将无法读取此类数据并将其放入模型中。最大日期和计数到哪里去了


    我不是在问怎么做。您总是可以以某种方式做到这一点:向存储库添加额外的方法、添加新类、特殊实体、使用LINQ等等,但我想我的问题如下。为什么存储库模式和适当的模型驱动开发被如此广泛地接受,但它们似乎没有解决这个看似非常常见和基本的问题

    我不能说我真的明白问题所在,只是在空中开火:

    • 添加特定实体以封装您想要的信息
    • 向帖子添加属性注释。(我不明白为什么这会要求你获取所有评论-你可以获取你正在加载的特定帖子的评论)
    • 使用延迟加载仅在访问属性时获取注释

    我认为,如果您将平台、语言和O/R映射器具体化(似乎是.NET C#或VB,因为您提到了LINQ.LINQ 2 SQL?实体框架?其他什么?),您将有更大的机会看到您的问题得到解答

    这个问题有很多。报告程序是否需要这些特定数据?如果是这样的话,那么正确的解决方案是为了报告目的而进行单独的数据访问。扁平化数据库、视图等

    或者这是一个特殊的查询需求?如果是这样的话,Ayende在这个问题上发表了一篇文章

    他使用“查找器”对象。他使用的是NHibernate,所以本质上他所做的是创建一个分离的查询

    我在过去也做过类似的事情,创建了一个查询对象,在将其交给存储库之前可以填充它(一些DDD纯粹主义者会反对它,但我发现它优雅且易于使用)

    Query对象实现了一个fluent接口,因此我可以编写此代码并返回结果:

    IQuery query = new PostQuery()
       .WithPostId(postId)
       .And()
       .WithCommentCount()
       .And()
       .WithCommentsHavingDateLessThan(selectedDate);
    
    
    Post post = _repository.Find(query);
    
    然而,在你的具体情况下,我不得不对你的设计感到惊讶。你是说你不能在帖子中加载评论。为什么?你只是过分担心表现吗?这是一种过早优化的情况吗?(在我看来是这样)


    如果我有一个Post对象,它将是我的聚合根,并且会附带注释。然后你想做的每件事都会在每一个场景中起作用

    由于我们需要紧急解决我在原始问题中概述的问题,我们采取了以下解决方案。我们向每个模型实体添加了一个属性集合(字典),如果DAL需要,它会将自定义数据粘贴到其中。为了建立某种类型的控制,属性集合由指定类的实例进行键控,并且它只支持简单的数据类型(整数、日期等),这是我们在移动时所需要的,并且很可能永远都需要。这解决的一个典型情况是:加载一个实体时,其子集合的计数不是完全填充的集合。我怀疑这可能不会因为软件设计而获得任何奖项,但对于我们的案例来说,这是最简单、最实用的解决方案。

    如果您没有被锁定在RDBMs中,那么像CouchDB或Amazons SimpleDB这样的数据库可能是值得一看的。在CouchDB视图中,您所描述的是微不足道的。这可能并不能真正回答您的具体问题,但有时最好看看完全不同的选项。

    为此,我通常有一个RepositoryStatus和一个Status类,作为我的数据传输对象(DTO)。Status类用于RepositoryStatus继承的my application service层(出于相同的原因)。然后用这个c
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using RanchBuddy.Core.Domain;
    using StructureMap;
    
    namespace RanchBuddy.Core.Services.Impl
    {
        [Pluggable("Default")]
        public class Status : IStatus
        {
            public Status()
            {
                _messages = new List<string>();
                _violations = new List<RuleViolation>();
            }
    
            public enum StatusTypes
            {
                Success,
                Failure
            }
    
            private object _object;
            public T GetObject<T>()
            {
                return (T)_object;
            }
            public void SetObject<T>(T Object)
            {
                _object = Object;
            }
    
            private List<string> _messages;
            public void AddMessage(string Message)
            {
                _messages.Add(Message);
            }
            public List<string> GetMessages()
            {
                return _messages;
            }
            public void AddMessages(List<string> Messages)
            {
                _messages.AddRange(Messages);
            }
    
            private List<RuleViolation> _violations;
            public void AddRuleViolation(RuleViolation violation)
            {
                _violations.Add(violation);
            }
            public void AddRuleViolations(List<RuleViolation> violations)
            {
                _violations.AddRange(violations);
            }
            public List<RuleViolation> GetRuleViolations()
            {
                return _violations;
            }
            public StatusTypes StatusType { get; set; }
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using RanchBuddy.Core.Services.Impl;
    using StructureMap;
    
    namespace RanchBuddy.Core.DataAccess.Impl
    {
        [Pluggable("DefaultRepositoryStatus")]
        public class RepositoryStatus : Status, IRepositoryStatus
        {
    
        }
    }