0

我正在尝试建立一对一的关系。如果没有必要,我不想使用 fluent 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; }

}

是的,我知道几乎没有类似的问题,但没有一个是简短而清晰的。他们中的很多也没有工作。

4

3 回答 3

4

这在一定程度上取决于您想要实现的表结构类型。有多种方法可以做到这一点,并且所有选项都有一个很好的演练,从这些链接中的共享主键关联到一对一外键关联。不幸的是,这些链接比 Annotations 更多地使用 Fluent。下面的示例根据需要使用注释。

共享主键

理论上共享主键(水平表分区,在数据库术语中)是“正确的方法”。这也是生成迁移所需的最小更改(将使用共享主键关联)。请注意,我将更改为Person.IdPerson.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关系)之间的关系。UserProfilePeople

如果您想使用IdPerson请执行以下操作(迁移将相应更改):

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

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

双向导航的共享主键

如果您想从 导航到UserProfilePerson您还有更多工作要做。简单地添加public virtual Person Person { get; set; }到 UserProfile 会给你一个错误:

无法确定类型“Test.Models.UserProfile”和“Test.Models.Person”之间关联的主体端。此关联的主体端必须使用关系流式 API 或数据注释显式配置。

因此,我们使用[Required]属性Person.UserProfile( Personrequires 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; }
}

同样,如果您使用IdforPerson而不是UserId

public class Person {
    [Key]
    public int Id { get; set; }
    [ForeignKey("Id")]
    [Required]
    public virtual UserProfile UserProfile { get; set; }
}
于 2013-05-27T13:38:53.390 回答
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; }
}
于 2013-05-27T12:45:04.987 回答
0

如果要创建一对一的关系,首先必须澄清什么是主体,什么是该关系中的依赖实体。可以Person存在没有UserProfile或可以UserProfile存在没有Person

因为您已经开始在我假设它是依赖项中应用一个[ForeignKey]属性,即没有.PersonPersonUserProfile

那么该属性的正确应用[ForeignKey]将是:

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

    public UserProfile UserProfile { get; set; }
}

我不确定这是否足够,因为您PersonUserProfile. 如果它不起作用,请将此属性添加到UserProfile

public Person Person { get; set; }

如果您不想拥有这样的导航属性,则无法避免 Fluent API:

modelBuilder.Entity<Person>()
    .HasRequired(p => p.UserProfile)
    .WithOptional();
于 2013-05-27T12:59:02.630 回答