У нас сложная бизнес-модель, и мы используем NHibernate для создания и обслуживания базы данных.Это приводит к низкой производительности время от времени, когда довольно прямой запрос приводит к большому графу объектов.
Обычно мы можем переписать запрос и получить хороший прирост производительности, в то же время лучше узнавая бизнес-модель.Однако теперь мы наткнулись на случай, когда мы не можем получить лучший результат, чем тот, который у нас есть в настоящее время, который, честно говоря, действительно очень плохой.
У нас есть следующие классы со связанными отображениями.Классы были сокращены до минимума, просто дайте мне знать, если вам нужна дополнительная информация.
public class GraphPoint
{
public DateTime datum;
public IDictionary<Avtal, Value> values;
public Calculation calculation;
public bool isCalculated;
public Int64 graphPointId;
...
}
public class Value
{
public int numbers;
public int points;
}
public class Avtal
{
public string name;
public Int64 avtalId
...
}
<class name="GraphPoint" lazy="false">
<id name="GraphPointId" column="GraphPointId" type="Int64">
<generator class="Business.Data.IncrementGenerator, Business"/>
</id>
<property name="Datum" not-null="true" unique-key="UIX1_GraphPoint" />
<map name="Values" table="GraphPointValue" cascade="all-delete-orphan">
<key column="GraphPointId" foreign-key="FK_GraphPoint_GraphPointValue" />
<map-key-many-to-many class="Avtal" column="AvtalId"
foreign-key="FK_GraphPoint_GraphPointValue_Avtal" />
<composite-element class="GraphPoint+Value">
<property name="Numbers" not-null="true" />
<property name="Points" not-null="true" precision="26" scale="15" />
</composite-element>
</map>
<property name="IsCalculated" not-null="true" />
<many-to-one name="Calculation" column="CalculationId"
foreign-key="FK_Calculation_GraphPoint" />
</class>
Итак, в этом сценарии мы используем следующие критерии: * Возвращаем все значения GraphPointValues между двумя датами * Агрегируем их на основе Avtalobject
В настоящее время мы пытаемся это сделать:
from punkt in (from punkt in Session.Query<GraphPoint>()
where punkt.IsCalculated &&
punkt.Datum >= lowDate &&
punkt.Datum <= highDate
select punkt).ToArray()
let values = from value in punkt.Values
where forAvtal.Contains(value.Key.AvtalId)
select value.Value
select new GraphPointValuePresentationObject
{
Datum = punkt.Datum,
Numbers = värden.Sum(v => v.Antal),
Points = värden.Sum(v => v.Poäng),
IsCalculated = punkt.IsCalculated
}
forAvtal - это список, содержащий идентификаторы для этих объектов, которые должны быть выполнены.
Когда мы запускаем это, мы получаем один sql-оператор для базы данных, который выбирает все GraphPoints, которые лежат между датами, а затем мы получаем один sql-statment для каждой и каждой из точек, которые первый SQL-операторвозвращает.
Я хочу переписать это так, чтобы нам потребовалась только пара SQL-операторов, а не несколько сотен, как сегодня.Кто-нибудь может дать мне указатель в правильном направлении, я пробовал Critierias и DetachedQueries, но не могу заставить его работать так, как я хочу.