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