简体   繁体   English

OOP中的数据库查询…设计模式?

[英]Database queries in OOP… design pattern?

This is the basic problem. 这是基本问题。 Say I have a base class Foo. 假设我有一个基类Foo。 This class does a call to the database to get some data to cache in the class. 此类调用数据库,以获取一些要缓存在该类中的数据。

public class Foo
{
    // Properties/fields go here.

    public virtual void ReadData()
    {
        // Queries the database for information and stores it in Foo.
    }
}

Now, say I have a derived class called Bar. 现在,假设我有一个名为Bar的派生类。 This class wants to cache some additional data. 此类想要缓存一些其他数据。

public class Bar : Foo
{
    // Additional properties/fields go here.

    public override void ReadData()
    {
        base.ReadData();

        // Queries the database for additional information and stores it in Bar.
    }
} 

Now, looking at this, it seems like a somewhat common thing to do if you were doing regular OOP. 现在,看一下这一点,如果您要进行常规的OOP,这似乎是一件常事。 But, in this case, you are accessing the database twice which is inefficient. 但是,在这种情况下,您要访问数据库两次,效率低下。 I'm working on a legacy codebase that does practices like this all over the place. 我正在使用一个遗留代码库,该代码库到处都在进行这种操作。 In the next release, they want database access optimization (meaning, less calls to the DB). 在下一发行版中,他们希望优化数据库访问(意味着减少对数据库的调用)。

Is there a design pattern for database access that would work with OOP so I can minimize the amount of queries on the DB? 是否有一种适用于OOP的数据库访问设计模式,因此我可以最大程度地减少对数据库的查询量?

The simplest trick would be to not to call the base class method. 最简单的技巧是调用基类方法。 Instead, let the inherited class use a specialized query to get the data in possibly one shot. 取而代之的是,让继承的类使用专门的查询来一次获取数据。

If your requirement is to lower the number of queries, oop has no magic for this. 如果您的要求是减少查询数量,则oop对此无可厚非。

Then, another option would be to have a caching proxy , this is a regular design pattern to deal with caching. 然后,另一个选择是拥有缓存代理 ,这是处理缓存的常规设计模式。

The general solution to this problem is to use composition, rather than inheritance . 解决此问题的一般方法是使用组合,而不是继承

Making this work most efficiently may also mean changing the design for your Foo type, so instead of caching data directly it only provides information about what things you want to cache. 使这项工作最有效地进行还可能意味着更改Foo类型的设计,因此,与其直接缓存数据,它仅提供有关要缓存的内容的信息。 Then another type would look at instances of Foo and Bar , compose together what they want to cache, and get everything in one call. 然后,另一种类型将查看FooBar实例,将它们要缓存的内容组合在一起,并在一次调用中获得所有内容。

Another wrinkle here is it's generally a bad idea for class objects to talk to the database directly. 另一个问题是类对象直接与数据库对话通常是个坏主意。 Typically, you want to have an object or a few objects grouped together to create a data access layer. 通常,您希望将一个对象或几个对象组合在一起以创建数据访问层。 All database access would go through these objects. 所有数据库访问都将通过这些对象。 Caching would take place at a higher level. 缓存将在更高级别进行。

What about building an expression tree defining the data to fetch and how to map the data? 如何构建一个表达式树来定义要提取的数据以及如何映射数据?

The parent class's ReadData() would ask for the data-to-fetch expression and do the fetching via a single SQL command. 父类的ReadData()将要求获取数据以获取表达式,并通过单个SQL命令进行获取。 Through overriding, child classes could add to, manipulate or replace the parent's expression, as desired. 通过覆盖,子类可以根据需要添加,操纵或替换父类的表达式。 Child classes would no longer need to query the db directly. 子类将不再需要直接查询数据库。

Writing the engine to convert the expression tree to SQL could take a bit of work.... 编写将表达式树转换为SQL的引擎可能需要一些工作。

In pseudo-code: Base Class 用伪代码:基类

public void ReadData() {
    var expression = DataExpression();
    var connection = // new db connection

    // translates the expression into SQL, executes the query, retrieves results, maps those results
    DataExpressionHelper::Process(expression, connection);
}
protected virtual SqlExpression DataExpression() {
    // Return an  expression tree like:
    //  From("BaseDataTable").Map("Name" => this.Name).Map("Age" => this.Age);
}

Child Class 儿童班

protected override SqlExpression DataExpression() {
    var expression = base.DataExpression();
    // Then, something to the effect of:
    //  expression += Join("ChildClassTable).On("parent.Id = child.ParentId).Map("Gender" => this.Gender);
}

If your question is (and it is) "Is there a design pattern for database access that would work with OOP so I can minimize the amount of queries on the DB?" 如果您的问题是(而且是) “是否存在一种可用于OOP的数据库访问设计模式,以便可以最大程度地减少数据库上的查询量?”

The answer is NO - no design pattern will minimize amount of queries. 答案是否定的 -没有设计模式可以最大程度地减少查询量。 It is the general design of your application that can lead to more or less queries. 应用程序的一般设计可能导致更多或更少的查询。

Look into this 3 things: 查看这三件事:

  1. Lazy Loading 延迟加载

  2. Caching 快取

  3. For performance of executing query: if you use dynamic Sql - parametrization of the Sql query will minimize resources used by DB Server to execute your query 为了提高执行查询的性能:如果使用动态Sql-Sql查询的参数化将最大限度地减少DB Server用于执行查询的资源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM