Модель Entity Framework: первая связь 1:0..1

Я создал следующую модель в конструкторе моделей Entity Framework 5 в Visual Studio 2012:

введите здесь описание изображения

Затем я сгенерировал базу данных из модели, в результате чего в моей базе данных появились следующие таблицы:

введите здесь описание изображения

Пожалуйста, помогите мне понять, почему Entity Framework создает отношение "один ко многим" для ассоциации "один к нулю или один".


Обновление №1

Кроме того, если я изменю ассоциацию с 1:0..1 на 1:1 следующим образом:

введите здесь описание изображения

Тогда в базе данных не только нет отношения один к одному, но теперь отношение один ко многим перевернуто, что мне кажется еще более странным:

введите здесь описание изображения


Обновление №2

В ответ на комментарий и ответ Mystere Man структура, которую я ожидаю увидеть в SQL Server, которая является допустимым отношением 1: 0.. 1, выглядит следующим образом:

введите здесь описание изображения

Кроме того, я могу заставить это работать точно так, как предполагалось, со следующим беглым отображением Code First:

public class UserMap : EntityTypeConfiguration<User>
{
    public UserMap()
    {
        ToTable("Users");

        HasKey(t => t.UserId);

        Property(t => t.UserId)
            .HasColumnName("UserId");

        Property(t => t.Name)
            .HasColumnName("Name")
            .IsRequired()
            .HasMaxLength(50);

        Property(t => t.EmailAddress)
            .HasColumnName("EmailAddress")
            .IsRequired()
            .HasMaxLength(254);

        Property(t => t.CreatedDateTime)
            .HasColumnName("CreatedDateTime");

        HasOptional(t => t.Subscription)
            .WithRequired(t => t.User);
    }
}

public class SubscriptionMap : EntityTypeConfiguration<Subscription>
{
    public SubscriptionMap()
    {
        ToTable("Subscriptions");

        HasKey(t => t.SubscriptionId);

        Property(t => t.SubscriptionId)
            .HasColumnName("SubscriptionId");

        Property(t => t.TypeValue)
            .HasColumnName("TypeValue");

        Property(t => t.CreatedDateTime)
            .HasColumnName("CreatedDateTime");

        Property(t => t.ExpiresDateTime)
            .HasColumnName("ExpiresDateTime");

        HasRequired(t => t.User)
            .WithOptional(t => t.Subscription);
    }
}

Итак, я знаю, что можно добиться такого поведения с помощью Code First Entity Framework. Мой вопрос в том, почему это невозможно сделать с подходом Model First.

Что здесь происходит и почему?

Спасибо!


comment
Как именно вы ожидаете, что модель данных будет выглядеть?   -  person Erik Funkenbusch    schedule 19.10.2013
comment
Пожалуйста, смотрите мое обновление № 2. Я ожидаю, что это будет выглядеть как правильное отношение 1: 0.. 1 в SQL Server.   -  person Tim S    schedule 21.10.2013
comment
Да, это сделало это. Спасибо!   -  person Tim S    schedule 21.10.2013


Ответы (1)


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

Единственный способ сделать это в SQL — сделать именно то, что здесь делает EF, создать 1:*, а затем наложить ограничения, обеспечивающие уникальность (например, уникальное ограничение). Однако EF не поддерживает ограничения (вам придется создавать их вручную), поэтому можно вставить более одной записи и нарушить вашу модель.

РЕДАКТИРОВАТЬ:

Поскольку вы пояснили, что говорите о Model First и ищете общий первичный ключ, то вот что вам нужно сделать.

Щелкните правой кнопкой мыши Ассоциацию и создайте реляционное ограничение между Подпиской и Пользователем. Это приведет к тому, что EF создаст отношение 1:0..1, которое вы ищете.

person Erik Funkenbusch    schedule 19.10.2013
comment
Я обновил свой вопрос, чтобы проиллюстрировать, что действительно возможно создать отношение 1: 0.. 1 с общим первичным ключом. Однако ключ не обязательно должен иметь одно и то же имя. Используя новый пример, который я предоставил в своем обновлении, можно добавить запись в таблицу Users в одном операторе, а затем запись в таблицу Subscriptions в следующем (но не наоборот) без нарушения каких-либо ограничений. Я также показал, как это возможно в EF Code First. - person Tim S; 21.10.2013
comment
@TimS - обратите внимание, что в моем ответе я специально сказал, за исключением случаев, когда оба объекта имеют один и тот же первичный ключ. Из вашего вопроса не похоже, что вы пытались использовать общий первичный ключ, поэтому я сформулировал это так, как сделал. Я бы, однако, предположил, что разные имена этих ключей сбивают с толку и нарушают соглашения об именах EF. Вы, конечно, можете переопределить их, как вы это сделали. Поскольку в вашем первоначальном вопросе не упоминалось совместное использование первичного ключа, а у вас были разные имена, было неясно, что вы имели в виду, и если мы, люди, не можем этого понять, как вы ожидаете, что EF? - person Erik Funkenbusch; 21.10.2013