这是基本问题。假设我有一个基类Foo。该类调用数据库以获取要在类中缓存的一些数据。
public class Foo
{
// Properties/fields go here.
public virtual void ReadData()
{
// Queries the database for information and stores it in Foo.
}
}
现在,假设我有一个名为Bar的派生类。这个类想要缓存一些额外的数据。
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.
}
}
现在,看看这个,如果你做普通的OOP,这似乎是一件很常见的事情。但是,在这种情况下,您访问数据库两次效率低下。我正在开发一个遗留代码库,可以在所有地方进行这样的实践。在下一个版本中,他们希望优化数据库访问(意味着,更少调用DB)。
答案 0 :(得分:3)
最简单的技巧是不来调用基类方法。相反,让继承的类使用专门的查询来一次性获取数据。
如果您的要求是降低查询次数,那么oop对此没有任何魔力。
然后,另一种选择是拥有缓存代理,这是一种处理缓存的常规设计模式。
答案 1 :(得分:1)
此问题的一般解决方案是use composition, rather than inheritance。
使这项工作最有效也可能意味着更改Foo
类型的设计,因此不直接缓存数据,而是仅提供有关要缓存的内容的信息。然后另一种类型会查看Foo
和Bar
的实例,将他们想要缓存的内容组合在一起,并在一次调用中获取所有内容。
另一个问题是,类对象直接与数据库通信通常是一个坏主意。通常,您希望将对象或几个对象组合在一起以创建数据访问层。所有数据库访问都将通过这些对象。缓存将在更高级别进行。
答案 2 :(得分:1)
如何构建定义要获取的数据以及如何映射数据的表达式树?
父类的ReadData()将要求数据获取表达式并通过单个SQL命令进行提取。通过覆盖,子类可以根据需要添加,操作或替换父表达式。子类不再需要直接查询数据库。
编写引擎以将表达式树转换为SQL可能需要一些工作......
在伪代码中: 基类
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);
}
儿童班
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);
}
答案 3 :(得分:0)
如果您的问题是(并且是) “是否存在可与OOP一起使用的数据库访问设计模式,以便最大限度地减少数据库上的查询量?” < /强>
答案是否 - 没有设计模式可以最大限度地减少查询量。应用程序的一般设计可能导致更多或更少的查询。
调查这三件事:
延迟加载
缓存
执行查询的性能:如果使用动态Sql - Sql查询的参数化将最小化DB Server用于执行查询的资源