如何优化城堡的ActiveRecord电话 [英] How do you optimize Castle ActiveRecord calls

查看:153
本文介绍了如何优化城堡的ActiveRecord电话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ASP.NET MVC 2 Web应用程序的

如何优化ActiveRecord的电话?

我坐在我的项目面前,一切都很好,直到我开始填写数据。像很多的项目,我有一个类似的数据结构:

一个星球上有许多国家。一个国家有许多州/省。一个国家有许多城市。一个城市有很多社区。

下面城堡的ActiveRecord / NHibernate的持久化业务对象的例子

  [ActiveRecord的]
公共类国家{

    [属性]
    公共字符串国家或地区名称{获得;组; }

    [的hasMany(typeof运算(美国))]
    公众的IList<国家>美国{获得;组; }
}
 

现在假设你想要做一个无辜的请求,就像得到所有国家的列表,在这个星球上

在默认情况下,ActiveRecord的/ NHibernate的将加载整个树,直到最后的依赖。

它可以变成是SQL调用了很多。

好了,就可以解决,与延迟加载 [ActiveRecord的(懒惰= TRUE)] 但只要你想要做的事整齐像下面

 字符串文本= + country.CountryName +这个国家有如下规定:;

的foreach(状态S在country.States)
{
    文字+ = s.StateName +;
}
 

通过延迟加载的ActiveRecord属性每次取了s.StateName时间它的另一个SQL调用。

这是太多的SQL调用。

我的一些朋友使用ActiveRecordBase等方法的FindAll(标准)建议。

但它最终被真正丑陋和难以阅读与所有这些防爆pression.Eq,什么不是。

然后其他人也建议使用类似的HQL。 HQL看起来像SQL很多。

所以底线,这似乎是最干净和最优化的方式是写简单明了的SQL查询。它去开门见山。

  SELECT * FROM国家//依赖的整个树的无负载

SELECT * FROM州,CountryId = @selectedId // 1电话,你把所有的状态
 

不管怎样,现在我使用的SQL查询和存储过程获取数据和ActiveRecord的保存/删除对象。

请纠正我,如果我错了......?

谢谢 鸭preciated。

解决方案

推荐的方法是使用懒映射在默认情况下,则预先抓取您所需要的每一种情况。

如果您不使用默认懒,你取pretty的太多整个数据库中的每个查询,因为你已经注意到了。

如果你使用懒惰的,但不急于获取,你碰上选择N + 1 的问题,你在你的foreach例子注意。

一切我所提到的,到目前为止是独立于你所使用的查询API的。这无论是使用HQL,标准的LINQ或QueryOver,你可以做所有。某些查询​​更容易EX preSS的HQL,和其他一些时候,它更方便地使用标准的LINQ或QueryOver。但同样,这是一个正交问题

此外,这是不是从其他计算机原始的SQL查询使用ADO.NET如此不同。在您的例子,如果你想要一个国家,它的状态,你将不得不作者结合,以获得发行个人选择每个状态的所有状态,而不是事先

How do you optimize ActiveRecord calls in your ASP.NET MVC 2 web applications ?

I'm sitting in front of my project and all is fine until I start to fill in data. Like a lot of projects I have a data structure similar to this:

A planet has many countries. A country has many states/provinces. A State has many cities. A city has many neighborhoods.

Below an example of Castle ActiveRecord/NHibernate persistent business object

[ActiveRecord]
public class Country {

    [Property]
    public String CountryName { get; set; }

    [HasMany(typeof(States))]
    public IList<State> States { get; set; }
}

Now suppose you want to do an innocent request like getting a list of all the countries on the planet

By default, ActiveRecord/Nhibernate will load the entire tree, until the very last dependency.

It can turn out to be A LOT of SQL calls.

Okay, we can solve that with lazy loading [ActiveRecord(lazy=true)] but then whenever you want to do something neat like below

String text = "This country of " + country.CountryName + " has the following states:";

foreach(State s in country.States)
{
    text += s.StateName + " ";
}

With the lazy load activerecord attribute every time it fetches for s.StateName it's another sql call.

That's way too many sql calls.

Some friends of mine suggested using ActiveRecordBase methods such as FindAll(criteria).

But it ends up being really ugly and hard to read with all those Expression.Eq and what not.

And then other people also suggested using something like HQL. HQL looks A LOT like SQL.

So bottom line, it seems like the most clean and optimized way is to write plain and simple SQL queries. It goes straight to the point.

SELECT * FROM Countries //No loading of an entire tree of dependencies

SELECT * FROM States WHERE CountryId = @selectedId   //1 call and you have all your states

Anyways, for now I'm using SQL queries and stored procedures for fetching data and ActiveRecord for saving/deleting objects.

Please correct me if I'm wrong... ?

Thanks Appreciated.

解决方案

The recommended way is using lazy mappings by default, then eagerly fetch what you need for each case.

If you don't use lazy by default, you fetch pretty much the whole database in each query, as you already noticed.

If you use lazy but don't fetch eagerly, you run into the SELECT N+1 issue you noticed in your foreach example.

Everything I mentioned so far is independent of the query API you use. You can do all of this using either HQL, Criteria, Linq or QueryOver. Some queries are easier to express in HQL, and some other times it's more convenient to use Criteria, Linq or QueryOver. But again, this is an orthogonal question.

Also, this isn't so different from runnning raw SQL queries with ADO.NET. In your example, if you wanted a country with its states you would have INNER JOINed to get all states beforehand instead of issuing individual SELECts for each state.

这篇关于如何优化城堡的ActiveRecord电话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆