如何在Entity Framework中使用流畅的api为一对一指定外键属性

时间:2015-04-14 20:17:04

标签: c# asp.net asp.net-mvc entity-framework ef-fluent-api

我有一张表User和另一张表CompanyUser可以注册零个或一个公司。

User (1)---> (0..1) Company

我的用户类:

public class User {
    public string Id {get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string FullName
    {
        get { return FirstName + " " + LastName; }
    }

    //Relations
    public virtual Company Company { get; set; }

}

我公司的课程是:

public class Company {
    public int Id { get; set; }        
    public string CompanyName { get; set; }
    public string TaxNumber { get; set; }
    public string TaxOffice { get; set; }
    public string OfficeTel { get; set; }
    public string FaxNumber { get; set; }
    public string WebSite { get; set; }
    public string Address { get; set; }
    public string About { get; set; }

    //keys
    public int CityId { get; set; }
    public int StateId { get; set; }                
    public string UserId { get; set; }

    //relations
    public City City { get; set; }
    public State State { get; set; }        
    public User User { get; set; }
}
用于公司的流利api是这样的:

public class CompanyConfiguration : EntityTypeConfiguration<Company>
{
    public CompanyConfiguration()
    {
        this.HasRequired(x => x.User)
            .WithOptional(x => x.Company);

        this.HasRequired(x => x.City)
            .WithMany(x => x.Companies).HasForeignKey(x => x.CityId).WillCascadeOnDelete(false);

        this.HasRequired(x => x.State)
            .WithMany(x => x.Companies).HasForeignKey(x => x.StateId).WillCascadeOnDelete(false);

        this.Property(x => x.Address).HasMaxLength(400);
        this.Property(x => x.CompanyName).HasMaxLength(100).IsRequired();
        this.Property(x => x.FaxNumber).HasMaxLength(20);
        this.Property(x => x.OfficeTel).HasMaxLength(20);
        this.Property(x => x.TaxNumber).HasMaxLength(20).IsRequired();
        this.Property(x => x.TaxOffice).HasMaxLength(50).IsRequired();
        this.Property(x => x.WebSite).HasMaxLength(200);            
    }
}

运行Add-Migration后,我期望UserIdUser表中用作Company的外键,但实体框架迁移生成的是:< / p>

CreateTable(
            "dbo.Companies",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    CompanyName = c.String(nullable: false, maxLength: 100),
                    TaxNumber = c.String(nullable: false, maxLength: 20),
                    TaxOffice = c.String(nullable: false, maxLength: 50),
                    OfficeTel = c.String(maxLength: 20),
                    FaxNumber = c.String(maxLength: 20),
                    WebSite = c.String(maxLength: 200),
                    Address = c.String(maxLength: 400),
                    About = c.String(),
                    CityId = c.Int(nullable: false),
                    StateId = c.Int(nullable: false),
                    UserId = c.String(),
                    User_Id = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Cities", t => t.CityId)
            .ForeignKey("dbo.States", t => t.StateId)
            .ForeignKey("dbo.AspNetUsers", t => t.User_Id)
            .Index(t => t.CityId)
            .Index(t => t.StateId)
            .Index(t => t.User_Id);

问题是如何强制实体框架将我的指定属性用作关系的外键,其原因是我需要在我的代码中经常使用公司的userId值,我不想使用Company.User.Id表达式来获得它。

注意:我使用Entity Framework 6.1.2和asp.net mvc 5

2 个答案:

答案 0 :(得分:0)

以下是我在此关系中定义外键的方法:

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

   [Required]
   [Key, ForeignKey("User")]
   public string UserId { get; set; }       

   public User User { get; set; }
}

答案 1 :(得分:0)

派对有点晚了,但只是把我的想法扔进了以防其他人遇到这个问题。

我自己也有同样的问题,实体框架(EF6)似乎没有为1-2-0 / 1关系指定外键的方式,但重要的是记住它被设计为被覆盖如果需要。我可以配置的唯一方法是手动修改自动生成的迁移文件。

实施例 下面是自动生成的迁移代码的缩写版本(如上所示),显示了作为FK的UserId和由EF插入的自动添加属性User_Id作为FK

    CreateTable(
        "dbo.Companies",
        c => new
            {
                Id = c.Int(nullable: false, identity: true),
                ...
                UserId = c.String(),
                User_Id = c.String(nullable: false, maxLength: 128),
            })
        .PrimaryKey(t => t.Id)
        ...
        .ForeignKey("dbo.AspNetUsers", t => t.User_Id)
        ...
        .Index(t => t.User_Id);

要实现UserId作为FK的初衷,只需删除autogenerated属性,然后修改FK语句和索引语句

    CreateTable(
        "dbo.Companies",
        c => new
            {
                Id = c.Int(nullable: false, identity: true),
                ...
                UserId = c.String(nullable: false, maxLength: 128),

            })
        .PrimaryKey(t => t.Id)
        ....
        .ForeignKey("dbo.AspNetUsers", t => t.UserId)
        ...
        .Index(t => t.UserId);

NB 问题中未显示还原迁移的Down方法,但对Up方法所做的任何添加或修改也需要反映在Down方法中。