Должны ли внешние ключи дедушки храниться в таблице внуков? - PullRequest
6 голосов
/ 28 января 2011

Каковы преимущества и недостатки включения ключей «дедушка + родитель» в таблицу.

Например, если моя объектная модель выглядит следующим образом.(Значительно упрощенный, поэтому он не подходит для использования в иерархической рекурсивной таблице.)

a {aId, bCollection, ...}
b {bId, cCollection, ...}
c {cId, dCollection, ...}
d {dId}

На ум приходят две опции модели данных:

опция 1:

a {pkA, ...}
b {pkB, fkA, ...}
c {pkC, fkB, ...}
d {pkD, fkC, ...}

вариант 2:

a {pkA, ...}
b {pkB, fkA, ...}
c {pkC, fkB, fkA, ...}
d {pkD, fkC, fkB, fkA, ...}

Вариант 1 более нормализован, вставки и обновления будут проще, но я вижу, что запросы становятся довольно сложными, особенно со многими отношениями и / или составными ключами.

Вариант 2 усложняет вставки и обновления, но извлечение отчетов будет проще.Кроме того, база данных будет больше, но меня это не особо волнует, так как в любом случае она довольно мала.

Но это довольно незначительные проблемы по сравнению с проблемами, которые возникают у ORM-подобной структуры сущностей.Я склоняюсь к варианту 2, потому что я хотел бы получить доступ к внукам напрямую от родителя следующим образом:

Class A { id, bCollection, cCollection, dCollection, ... }
Class B { id, cCollection, dCollection, ... }
Class C { id, dCollection, ... }
Class D { id, ...}

Платформа сущностей 4.0 изящно обрабатывает эту ситуацию?Каковы плюсы и минусы двух вариантов?Есть ли другая альтернатива, которую я должен рассмотреть?

Или, проще говоря, как, черт возьми, этот гугл задает такой любопытный вопрос?в значительной степени к варианту A, но я знаю, что прочитал статью msdn, в которой подробно рассказывается, почему вариант B лучше.К сожалению, я не могу найти это.: (

Заранее спасибо за ваши мысли.

Ответы [ 3 ]

6 голосов
/ 28 января 2011

Я бы избегал варианта Б, как чумы.Ни один из этих вариантов не является существенно более сложным для запроса, чем другой, но второй вариант сложнее поддерживать на намного и требует нормализации для параметра А.

Для запроса варианта А,все, о чем вы говорите - это добавление простых соединений.Поскольку это не рекурсивное отношение, вы должны уже заранее знаете, на сколько уровней "глубоко" может пройти запрос, поэтому вам не нужно беспокоиться о том, что он хрупкий или работает только для подмножествапотенциальных кейсов.

Сравните, выбрав самый глубокий кейс, в котором вы ищете родительского уровня глубоко вложенного узла:

Опция A:

select
    a.id

from d

join c on c.id = d.c_id
join b on b.id = c.b_id
join a on a.id = b.a_id

where d.id = @id

Вариант B:

select a_id from d where id = @id

Вариант A больше сложен?Да, но никому не должно быть сложно выяснить, что происходит.

Что касается совместимости с EF4, это не проблема.Вы можете линейно перемещаться по цепочке родителей, чтобы найти нужного вам дедушку.Вы можете сделать это в коде или в запросе;любой из них будет работать нормально:

В коде:

var entity = context.D.Where(d => d.Id == 4).First();
var grandParent = entity.C.B.A;

В запросе (с использованием LINQ и объединений):

var grandparent = (from d in context.D
                   join c in context.C on d.CId == c.Id
                   join b in context.B on c.BId == b.Id
                   join a in context.A on b.AId == a.Id

                   where d.Id == id

                   select a // or a.Id).First();

В запросе (с использованием свойств навигации):

var grandparent = (from d in context.D
                  where d.Id == id
                  select d.C.B.A // or d.C.B.A.Id).First();
3 голосов
/ 28 января 2011

Я бы сказал, что если БД имеет хорошую поддержку рекурсивных отношений (т. Е. Oracle отлично справляется с этим, а некоторые другие имеют специфический синтаксис для этих запросов), то используйте рекурсивный (ваш вариант A).В противном случае вы застрянете несколько дней в отладке своего кода, убедившись, что вы обновляете все записи, которые нужно обновить, когда отношения изменяются, и вам нужно каскадировать изменения вручную.

А для Google используйтетермин "рекурсивные таблицы" или "рекурсивные запросы".

3 голосов
/ 28 января 2011

Если ваша база данных в основном OLTP, я бы выбрал вариант A. Если ваши отчеты становятся проблемой, вы можете создать представление или денормализованную таблицу для представления варианта B.

Если ваша база данных в основном OLAP,Я бы пошел с вариантом B.

...