2013-05-27 4 views
0

Я пытаюсь установить отношения один к одному. Я не хочу использовать свободный API, если он не нужен. Это то, что я пытался до сих пор:Индивидуальные отношения - сначала код

[Table("UserProfile")] 
public class UserProfile 
{ 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
} 
    public class Person 
{ 
    public int Id { get; set; } 

    [ForeignKey("UserId")] 
    public UserProfile UserProfile { get; set; } 

} 

Да, я знаю, что есть несколько подобных вопросов Outhere, но ни один из них не было коротко и ясно. Многие из них тоже не работали.

+1

Спасибо .Down голос помогает. –

+0

Можем ли мы проверить, какую версию MVC и EF вы используете - это может иметь значение в ваших ответах. –

+0

MVC 4, Entity Framework 5 –

ответ

4

Это зависит немного на какой тип структуры таблицы вы хотите достичь. Существуют различные способы сделать это, и есть хорошее пошаговое руководство для всех вариантов, от Shared Primary Key Assocations до One-to-One Foreign Key Associations в этих ссылках. К сожалению, эти ссылки больше используют Fluent, чем Annotations. В приведенных ниже примерах используются аннотации, как вам нужно.

Shared Первичный ключ

В теории Shared Первичный ключ (горизонтальная таблица разделов, в терминах базы данных) является «правильный путь». Это также самое малое изменение, которое вы должны сделать, чтобы иметь возможность генерировать миграцию (которая будет использовать Ассоциацию общих первичных ключей). Обратите внимание, что я хотел бы изменить Person.Id к Person.UserId лучше показать свое намерение:

// tested in EF 5 and MVC 4.5. 
[Table("UserProfile")] 
public class UserProfile { 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
} 
[Table("Person")] // not required, added for clarity in sample code 
public class Person { 
    // Note the change of property name to reflect that this is a shared primary key, 
    // using the UserId column in UserProfile as the Primary Key 
    [Key] 
    public int UserId { get; set; } 
    [ForeignKey("UserId")] 
    public virtual UserProfile UserProfile { get; set; } 
} 
// The generated migration: 
public partial class AddTable_Person : DbMigration 
{ 
    public override void Up() { 
     CreateTable(
      "dbo.Person", 
      c => new { 
        UserId = c.Int(nullable: false), 
       }) 
      .PrimaryKey(t => t.UserId) 
      .ForeignKey("dbo.UserProfile", t => t.UserId) 
      .Index(t => t.UserId); 
    } 
    public override void Down(){ 
     DropIndex("dbo.Person", new[] { "UserId" }); 
     DropForeignKey("dbo.Person", "UserId", "dbo.UserProfile"); 
     DropTable("dbo.Person"); 
    } 
} 

это то дает вам, в действительности есть 1:0-1 отношения между UserProfile (который является обязательным) и People (который является необязательным, но может иметь один пер человек в наиболее

Если вы хотите использовать Id в Person затем выполните следующие действия (миграция будет меняться соответственно).

public class Person { 
    public int Id { get; set; } 

    [ForeignKey("Id")] 
    public UserProfile UserProfile { get; set; } 
} 

Shared Первичный ключ с двухсторонней навигации

Если вы хотите перейти от UserProfile к Person у вас есть больше работы.Простое добавление public virtual Person Person { get; set; } к UserProfile даст вам ошибку:

Unable to determine the principal end of an association between the types 'Test.Models.UserProfile' and 'Test.Models.Person'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

Итак, зафиксируем его [Required] на Person.UserProfile собственности (Person требует UserProfile). Это дает такую ​​же миграцию, как и раньше.

// tested in EF 5 and MVC 4.5. 
[Table("UserProfile")] 
public class UserProfile { 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
    [ForeignKey("UserId")] 
    public virtual Person Person { get; set; } 
} 
[Table("Person")] // not required, added for clarity in sample code 
public class Person { 
    [Key] 
    public int UserId { get; set; } 
    [ForeignKey("UserId")] 
    [Required] 
    public virtual UserProfile UserProfile { get; set; } 
} 

Опять же, это работает, если вы используете Id для Person вместо UserId:

public class Person { 
    [Key] 
    public int Id { get; set; } 
    [ForeignKey("Id")] 
    [Required] 
    public virtual UserProfile UserProfile { get; set; } 
} 
+0

+1: Хороший анализ! Странная вещь, которую я обнаружил, заключается в том, что для двусторонней навигации добавление '[ForeignKey (« UserProfile »)]' on 'Person.UserId' работает без атрибута' [Обязательный] 'и без атрибута FK в' UserProfile', но это не так поместите '[ForeignKey (« UserId »)]' без атрибута '[Обязательный]' в 'Person.UserProfile' - если вы не удалите свойство навигации UserProfile.Person. Полностью запутанный для меня ... – Slauma

+0

@Slauma. Он делает, хотя я предпочитаю его с 'Обязательным' в свойстве' virtual UserProfile', так как он помогает объявить намерение - чисто личное предпочтение. –

0
[Table("UserProfile")] 
public class UserProfile 
{ 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
    public virtual Person Person {get;set;} 
} 

public class Person 
{ 
    public int Id { get; set; } 

    public int UserProfileUserId { get; set; } //Foreign Key 
    public virtual UserProfile UserProfile { get; set; } 
} 
+0

Не работает. Вот почему я сказал, что в этой теме действительно огромное количество неверных ответов. Вот почему мне так нравится человек, который ниспровергнут. –

+0

@impeRAtoR: Оо я забыл изменить класс Userprofile ... проверить сейчас ... –

0

Если вы хотите создать отношения один-к-одному первое, что вы должны выяснить, что является главным и что зависимая сущность в этих отношениях. Может ли Person существует без UserProfile или может UserProfile существует без Person?

Поскольку вы начали применять атрибут [ForeignKey] в Person я сейчас предполагаю, что Person является зависимой, то есть он не может существовать без UserProfile.

Правильное применение атрибута [ForeignKey] бы тогда:

public class Person 
{ 
    [ForeignKey("UserProfile")] 
    public int Id { get; set; } 

    public UserProfile UserProfile { get; set; } 
} 

Я не уверен, что это достаточно, потому что вы не имеете Person свойство навигации в UserProfile. Если он не работает добавить это свойство в UserProfile:

Если вы не хотите иметь такое свойство навигации вы не можете избежать Fluent API:

modelBuilder.Entity<Person>() 
    .HasRequired(p => p.UserProfile) 
    .WithOptional(); 
+0

ИМХО, 'modelBuilder.Entity () .HasRequired (р => p.UserProfile) .WithOptional();' является FLUENT API-код, который пользователь не хочет использовать. –

+0

Я могу свободно использовать api, это не проблема, мне также нравятся навигационные свойства, да, человек не может существовать без UserProfile –

+0

@BhushanFirake: «* если это не обязательно *", он сказал. Но это (возможно) необходимо, если он не хочет иметь свойство навигации UserProfile.Person. У него есть выбор: либо свойство навигации, либо Fluent API. Возможно, это необязательно даже без свойства навигации, потому что атрибут FK относится к ПК, и, возможно, EF достаточно умен, чтобы понять, что FK, который является ПК в одно и то же время, может участвовать только в отношениях один к одному. Я не уверен в этом. – Slauma

Смежные вопросы