代码优先一对一关系

时间:2015-01-25 14:13:06

标签: c# asp.net-mvc entity-framework ef-code-first data-annotations

为我有两个表(客户和用户)的情况编写模型。每个用户记录可能具有可选的相关客户记录,反之亦然,但它们都不是必须的。我发现FK Associations不是我需要的,但是Independent Associations。但是我只能找到一种方法使它工作,我不断得到“无法确定主要结束...”必须使用关系流畅的API或数据注释显式配置此关联的主要结尾。 #39;例外。

我的模型非常简单:

public class User
{
    [Key]
    public int          Id              { get; set; }
    [StringLength(20)]
    public string       CustomerId      { get; set; }
    public string       Password        { get; set; }
    public bool         Locked          { get; set; }

    //[ForeignKey("CustomerId")]
    public virtual Customer Customer    { get; set; }
}

public class Customer
{
    [Key]
    [Column("Id", TypeName = "nvarchar")]
    [StringLength(20)]
    public string       Id              { get; set; }   //  nvarchar    20
    [Required]
    public string       GivenName       { get; set; }   //  nvarchar    100
    [Required]
    public string       Surname         { get; set; }   //  nvarchar    100

    //[InverseProperty("Customer")]
    public virtual User User            { get; set; }
}

我试图添加当前已注释掉的ForeignKeyAttribute和InversePropertyAttribute,但它们也没有帮助。如果我的情况可行,我宁愿使用数据注释而不是流畅的API。

1 个答案:

答案 0 :(得分:1)

一对一关系中,一端必须主体,第二端必须依赖 Principal end是将首先插入的,并且可以在没有依赖的情况下存在的那个。 依赖结束是必须在主体之后插入的结尾,因为它具有主体的外键。在配置一对一关系时,实体框架要求依赖关系的主键也是外键。通过在依赖类上使用ForeignKey注释来识别它包含的是,这个问题最容易解决。外键。在您的情况下,Customer可能是依赖项,其密钥Customer.UserId也应该是外键。但是必须使用相同的类型声明两个键:

public class User
{
   [Key]
   public int  Id  { get; set; }

   public virtual Customer Customer { get; set; }
}

public class Customer
{
   [Key, ForeignKey("User")]
   public int  UserId { get; set; }

   public virtual User User{ get; set; } 
}

我不知道如何使用数据注释来解决您的问题,但如果您想使用Fluent Api,我认为关系的配置将是这样的:

 modelBuilder.Entity<User>().HasOptional(u => u.Customer).WithOptionalPrincipal(c => c.User);

更新

我理解您的情景,但是如果您在模型中显示的列相同,我认为您应该在数据库中映射一对多关系而不是一对一。尝试以这种方式映射您的关系:

public class User
{
    [Key]
    public int Id { get; set; }

    public string Password { get; set; }
    public bool Locked { get; set; }

    public string CustomerId { get; set; }

    [ForeignKey("CustomerId")]
    public virtual Customer Customer { get; set; }
}

public class Customer
{
    [Key]
    [Column("Id", TypeName = "nvarchar")]
    [StringLength(20)]
    public string Id { get; set; }   //  nvarchar    20
    [Required]
    public string GivenName { get; set; }   //  nvarchar    100
    [Required]
    public string Surname { get; set; }   //  nvarchar    100

    public virtual  ICollection<User> Users { get; set; }
}

请记住使用与DB中相同的列名来映射您的属性。