RE:CRUD操作它会提取比所需更多的数据是一件坏事吗? 摘要数据的自定义结果

问题描述

RE:CRUD操作...是否会提取比所需更多的数据呢?

让我在开头说我确实确实在寻找这个答案。现在打开和关闭一段时间。我敢肯定之前已经有人问过/回答过,但似乎找不到。大多数文章似乎都针对如何执行基本的CRUD操作。我真的很想深入了解最佳做法。话虽如此,这是我为示例目的而模拟的示例模型。

public class Book
{
    public long Id { get; set; }
    public string Name { get; set; }
    public decimal Averagerating { get; set; }
    public decimal ArPoints { get; set; }
    public decimal BookLevel { get; set; }
    public string Isbn { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime PublishedAt { get; set; }

    public Author Author { get; set; }
    public IEnumerable<Genre> Genres { get; set; }
}

我正在使用ServiceStack的Ormlite,并尽可能将字符串查询迁移到对象模型绑定。这是一个C#MVC.NET项目,使用带有DI的Controller / Service / Repository层。我最大的问题是读取和更新操作。以读取为例。出于示例目的,这是两种方法(仅写了我认为与之相关的内容)。

public class BookRepository
{
    public Book Single(long id)
    {
        return _db.SelectById<Book>(id);
    }

    public IEnumerable<Book> List()
    {
        return _db.Select<Book>();
    }
}

无论在现实世界中需要如何改变,问题都只是返回了很多信息。假设我正在向用户显示图书清单。即使List方法的编写方式使其不提取嵌套方法(作者和流派),它也会包含未使用的属性的数据。

似乎我可以学习获取不需要的数据,或者编写一些额外的方法来更改提取属性。使用Single方法,下面是一些示例...

public Book SinglePublic(long id): Returns a few properties
public Book SingleSubscribed(long id): Returns most properties
public Book SingleAdmin(long id): Returns all properties

对于大多数表来说,必须写出这样的方法对我来说似乎不太可维护。但是,然后,几乎总是在大多数呼叫中获取未使用的信息会影响性能,对吗?我必须丢失一些东西。任何帮助将不胜感激。随便分享一个链接,给我看PluralSight视频,推荐一本书,随便什么。我对任何事情都开放。谢谢。

解决方法

通常,您应该避免过早的优化,并始终首先从最简单,最有生产力的解决方案开始,因为避免complexity & large code-base sizes应该是您的首要任务。

如果仅获取一行,则绝对应仅使用单个API并获取完整的Book实体,我个人还将避免Repository抽象,我认为这是不必要的抽象,所以我将直接在您的Controller或Service中使用OrmLite API,例如:

Book book = db.SingleById<Book>(id);

您绝对不会注意到RDBMS网络调用的I / O成本之外的其他未使用字段,并且App与RDBMS之间的延迟和带宽远远超过Internet上的其他信息。为了减少未使用的字段而拥有多个API会增加不必要的复杂性,增加代码库的大小/增加技术负担,降低代码的可重用性,可缓存性和可重构性。

何时为单个实体考虑多个数据库调用:

  1. 您已经收到反馈,并给出了改善页面/服务性能的任务
  2. 您的实体包含大块的文本或诸如图像之类的二进制字段

第一句话是通过在优化以解决已知的可实现性能问题之前首先关注简单性和生产率来避免过早优化。在这种情况下,请先分析代码,然后如果显示问题出在数据库查询中,则可以优化为仅返回该API /页面所需的数据。

为了提高性能,我通常首先评估缓存是否可行,因为它通常是最省力/最大价值的解决方案,在该解决方案中,您可以轻松地使用[CacheResponse] attribute缓存API,该API将在指定的持续时间内缓存最佳的API输出或者您可以利用caching primitives in HTTP来避免需要通过网络返回任何未修改的资源。

为避免第二个问题,即在没有大数据的情况下进行不同的查询,我将其提取到不同的 1:1 行中,并仅在需要时才检索它,因为大行大小会损害整体性能访问该表。

摘要数据的自定义结果

因此,很少有不同的API来访问单个实体的不同字段(更可能是由于附加连接),但是对于返回同一实体的多个结果,我将拥有仅包含数据的不同优化视图需要。此现有答案显示了retrieve custom resultsets with OrmLite的一些方法(另请参见OrmLite文档中的Dynamic Result Sets)。

通常,我更喜欢将custom Typed POCO与我想让RDBMS返回的字段一起使用,例如在摘要BookResult实体中:

var q = db.From<Book>()
  .Where(x => ...);
var results = db.Select<BookResult>(q);

这都是与手头任务有关的,例如返回的结果越少或访问Page / API的并发用户越少,使用多个优化查询的可能性就越小;而对于具有1000个并发用户并具有频繁访问功能的公共API,我肯定希望经常进行性能分析和优化每个查询。尽管通常会从那些将“绩效是一项功能”作为主要目标并分配相应的时间和资源的利益相关者那里弄清楚这些情况。

,

我无法与ORM Lite对话,但是对于Entity Framework,ORM会向前看,并且仅返回完成后续执行所需的列。如果将其与视图模型结合使用,那么您将处在一个不错的位置。因此,例如,假设您有一个网格来显示书籍的标题。您只需要数据库中的一部分列即可。您可以创建一个这样的视图模型:

public class BookListViewItem{
  public int Id {get;set;}
  public string Title {get; set;}

  public BookListView(Book book){
    Id = book.Id;
    Title = book.Title;
  }
}

然后,当需要时,像这样填充它:

var viewModel = dbcontext.Books
                         .Where(i => i.whateverFilter)
                         .Select(i => new BookListViewItem(i))
                         .ToList();

这应该将生成的SQL限制为仅请求idtitle列。

在实体框架中,这称为“投影”。参见:

https://social.technet.microsoft.com/wiki/contents/articles/53881.entity-framework-core-3-projections.aspx

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...