Создание двунаправленной связи One-One в Entity Framework 4.1 Code First - PullRequest
11 голосов
/ 08 июня 2011

Я хочу создать двунаправленную связь One-One между двумя объектами, используя EF Code First. У меня проблема со следующим кодом. Как вы думаете, что я должен делать?

public class User
{
    public string ID { get; set; }
    public string LastName { get; set; }
    public string Password { get; set; }
    public string FirstName { get; set; }

    public int ProfileID { get; set; }
    public Profile Profile { get; set; }

}
public class Profile
{
    public int UserID { get; set; }
    public User User { get; set; }
    public int ProfileID { get; set; }
    public string ProfileName { get; set; }

    public DateTime CreateDate { get; set; }
    public DateTime LastUpdateDate { get; set; }

}

Я хочу, чтобы в обоих объектах было свойство Navigation и Foreign Key.

Это дает мне ошибку. Что я могу сделать в API Fluent Mapping, чтобы это работало?

1 Ответ

18 голосов
/ 08 июня 2011

Используйте это:

public class User
{
    public string ID { get; set; }
    public string LastName { get; set; }
    public string Password { get; set; }
    public string FirstName { get; set; }
    public Profile Profile { get; set; }
}

public class Profile
{
    [Key, ForeignKey("User")]
    public int ProfileID { get; set; }
    public string ProfileName { get; set; }
    public DateTime CreateDate { get; set; }
    public DateTime LastUpdateDate { get; set; }
    public User User { get; set; }
}

Это единственный действительный способ построения взаимно-однозначного отношения в EF - PK зависимого объекта также должен быть FK для основного объекта. В EF нет ничего похожего на двунаправленное взаимно-однозначное отношение, потому что оно не может работать в EF.

Способ, которым люди иногда преодолевают это, - это два отношения «один ко многим», когда у принципала нет коллекции навигации для зависимых объектов + определяемые вручную уникальные ключи в базе данных. Это требует ручного отображения:

public class User
{
    public string ID { get; set; }
    public string LastName { get; set; }
    public string Password { get; set; }
    public string FirstName { get; set; }
    // one side MUST be nullable otherwise you have bidirectional constraint where each
    // entity demands other side to be inserted first = not possible
    public int? ProfileId { get; set; } 
    public Profile Profile { get; set; }
}

public class Profile
{
    public int ProfileID { get; set; }
    public string ProfileName { get; set; }
    public DateTime CreateDate { get; set; }
    public DateTime LastUpdateDate { get; set; }
    public int UserId { get; set; }
    public User User { get; set; }
}

А в отображении вы определите:

modelBuilder.Entity<User>
            .HasOptional(u => u.Profile)
            .WithMany()
            .HasForeignKey(u => u.ProfileId);
modelBuilder.Entity<Profile>
            .HasRequired(u => u.User)
            .WithMany()
            .HasForeignKey(u => u.UserId);

Теперь вы должны определить уникальные ключи в базе данных - если вы используете код, сначала используйте пользовательскую базу данных, инициализируйте r. Имейте в виду, что двунаправленное взаимно-однозначное отношение является неправильным понятием, поскольку обе стороны требуют уникального FK, в котором NULL по-прежнему включается в уникальные значения, поэтому после вставки User перед Profile не должно быть никаких других User без Profile. Это, вероятно, приводит к сериализуемой транзакции.

...