Здравствуйте, <Аноним>, Вы писали:
А>Само собой не всегда они нужны сразу одной группой. Я бы хотел чтобы кто-нибудь привел действительно веские причины почему данные которые не всегда нужны нужно отделять в отдельную таблицу/класс. Как я уже сказал, email клиента не всегда нужен, что же, его отделять в отдельную таблицу/класс?
Различие принципиальное, вам говорили о нем выше... попробую пожевать сильнее:
С одной стороны, есть некоторый набор свойств сущности, которыми независимо от обстоятельств обладает каждый представитель: к примеру, login/password, ФИО, паспортные данные и т.п. есть у каждого пользователя — если свойства пользователя дополнили полем e-mail, значит предполагается, что большинство пользователей пользуются электронной почтой.С другой стороны, есть некоторый набор свойств только некоторых представителей сущности: далеко не у каждого пользователя есть семья, машина и т.п. В этом случае использовать one-to-one — значит правильно класть колбасу на хлеб. Если расширяем основную таблицу, то имеем море записей с NULL, а значит познаем все прелести троичной логики в коде, который работает в основном по двоичной логике.
Рассмотрим на примере. В случае one-to-one предикат отсутствия данных о семье:
user.Family == null
- нет семьи, а значит нет записи в соответствующей таблице, а значит на уровне кода тоже ничего нет, а значит не генерируется никаких лишних выборок SQL-запросом — если нет данных о семье, объект Family попросту не будет создан. А в случае плоской таблицы предикат что-то вроде:
user.HasFamily
- вводится дополнительное NotNull-свойство, это еще более или менее нормально, а то ведь обычно происходит примерно такая бяка:
user.WifeHusbandName is DbNull
При этом происходит происходит практически SQL-мегазапрос типа
select * from Users
, то есть даже для пользователей без семей создаются структуры с DbNull-ами, а потому определение факта отсутствия данных о семье плавно переносится в код — дизайн достойный сожаления. Кроме того, во втором случае очень неудобно кодирование ленивой загрузки данных о семье.
Еще раз о различии user.Email и User.Family:
Истинность:Users.email is null
обычно означает факт отсутствия данных об электронной почте пользователя (то есть пока не знаем адрес, но скоро узнаем и укажем), предполагается, что это не должно означать то, что у пользователя нет электронной почты, но даже если и так, то это не страшно, если бизнес-логика приложения не требует различать эти факты. И это хорошо.Если результат запроса:select
count(*)
from UserFamilies
join Users on
UserFamilies.userId = Users.id
where
Users.id = @userId
равен 0, это означает факт отсутствия семьи пользователя. Если > 0, имеем факт наличия семьи (быть может и не одной). То есть четкая определенность. Примечательно, что подобный запрос очень удобно кодируется для ленивой загрузки. И это все тоже хорошо.
А вот что означает в случае плоской таблицы это:Users.WifeHusbandName is null
То ли, что у пользователя нет семьи, то ли что просто пока имя супруги/супруга не известно. Эта неопределенность в большинстве случаев не есть хорошо, это есть очень плохо.
По теме можно прочитать вот это:
NULL, трехзначная логика и неопределенность в SQL: критика критики Дейта, Клод Рубинсон
Критика критики критики Дейта