Иерархическая сущность

Здравствуйте!

Проблема стоит следующая: создать иерархическую(или скорее графоподобную) сущность, каждый элемент которой мог бы иметь как несколько детей, так и несколько предков и потому стандартная реализация через колонку ParentId не подходит. Вопрос следующий: как правильно(если вообще возможно) создать такую структуру данных, чтобы потом можно было выбрать всех предков скажем так:

Select accountSelect = GetAccountSelectQuery(accountId, additionalColumnNames);
var hierarhicalOptions = new HierarchicalSelectOptions {
PrimaryColumnName = "AccountId",
ParentColumnName = "ParentAccountId",
SelectType = HierarchicalSelectType.Parents,
MaxDepthParameter = select.Parameters.GetByName("MaxDepth"),
IncludeLevelColumn = true
};
QueryCondition startingCondition = hierarhicalOptions.StartingPrimaryColumnCondition;
startingCondition.LeftExpression = new QueryColumnExpression("AccountId");
startingCondition.IsEqual(select.Parameters.GetByName("RootAccountId"));
string sqlText = UserConnection.DBEngine.GetQuerySqlText(accountSelect, hierarhicalOptions);
using (DBExecutor dbExecutor = UserConnection.EnsureDBConnection()) {
using (IDataReader reader = dbExecutor.ExecuteReader(sqlText, accountSelect.Parameters)) {
while (reader.Read()) {
ancestors.Add(reader.GetColumnValue("AccountId"););
}

Нравится

2 комментария

Добрый день, Андрей!

Идея Ваша ясна, но реализовать вот прямо как код написан вряд ли удастся, только если писать какие-то костыли. Допустим, а) если количество предков или наследников или наследников будет строго меньше N, можно сделать N полей, но это плохо с той стороны, что большое количество полей будет просто излишним, б) сделать какое-то поле, в котором будут сконкатенированы, допустим, через запятую id`шники предков, и потом его парсить, но это нарушение реляционности, да и в принципе очень проблематично. Рекомендую все же пересмотреть иерархию и подобрать другое решение.

Советую посмотреть деталь взаимосвязей и сделать аналогично (только там программное ограничение на одного родителя, но это тоже можно обойти)

Показать все комментарии