与可空外键的一对一关系

Ale*_*kov 0 c# entity-framework one-to-one

我想在EF中创建一对一关系,其中外键可以为null(因此,它可以被称为0..1到0..1)

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

    public int SaleId { get; set; }
    public Sale Sale { get; set; }
}


public class Sale
{
    public int Id { get; set; }
    public ProductInstance ProductInstance { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

FluentAPI 组态:

modelBuilder.Entity<Sale>()
   .HasOptional(x => x.ProductInstance)
   .WithOptionalPrincipal(x => x.Sale);
Run Code Online (Sandbox Code Playgroud)

但它在表中生成两列ProductInstance:

  • Sale_id - 外键
  • SaleId

这是生成的迁移代码:

 CreateTable(
            "dbo.ProductInstances",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    SaleId = c.Int(nullable: false),
                    Sale_Id = c.Int(),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Sales", t => t.Sale_Id)
            .Index(t => t.Sale_Id);
Run Code Online (Sandbox Code Playgroud)

如何才能只获得一列SaleId外键?

Tan*_*jel 5

一对一或一对一的关系:

当一个表的主键在关系数据库(如SQL Server)中的另一个表中变为PK&FK时,会发生一对多或一对一的关系.

数据注释一对一或一,如下:

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

    public virtual Sale Sale { get; set; }
}


public class Sale
{
    [Key]
    [ForeignKey("ProductInstance")]
    public int ProductInstanceId { get; set; }

   ///write here other properties

    public virtual ProductInstance ProductInstance { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

使用Fluent API进行一对一或一对一,如下所示:

modelBuilder.Entity<ProductInstance>()
                .HasOptional(s => s.Sale)
                .WithRequired(ad => ad.ProductInstance);
Run Code Online (Sandbox Code Playgroud)

在上述情况下,ProductInstance可以保存a,Sale但是没有Sale实体就无法保存ProductInstance实体.在上述情况下保持最小,A ProductInstance不能超过一个Sale.

一对一的关系:

我们无法在需要两端的实体之间配置一对一关系,这意味着ProductInstance实体对象必须包含Sale实体对象,并且Sale实体必须包含ProductInstance实体对象才能保存它.在MS SQL Server中,技术上不可能实现一对一关系.但我们可以在实体之间配置一对一关系,其中两端或至少一端是可选的,如下所示:

与Data Annotation一对一如下:

public class Department
{
    [Key]
    public int DepartmentId { get; set; }

    ForeignKey("Person")]
    public int PersonId { get; set; }

    public virtual Person Person { get; set; }
}


public class Person
{
    [Key]
    public int PersonId { get; set; }

    [ForeignKey("Department")]
    public int? DepartmentId { get; set; }


    public virtual Department Department { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

与Fluent API一对一如下:

modelBuilder.Entity<Person>()
                .HasOptional(pi => pi.Department)
                .WithMany()
                .HasForeignKey(s => s.DepartmentId);
Run Code Online (Sandbox Code Playgroud)


Iva*_*oev 5

EF不支持one-to-one具有显式FK属性的关联-没有HasForeignKey流畅的API,并且如果您尝试通过ForeignKey数据注释来解决它,则在迁移期间会遇到多重异常。

唯一的解决方案是删除ProductInstance.SaleId属性,最终得到模型:

public class ProductInstance
{
    public int Id { get; set; }
    public Sale Sale { get; set; }
}

public class Sale
{
    public int Id { get; set; }
    public ProductInstance ProductInstance { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

和配置:

modelBuilder.Entity<Sale>()
   .HasOptional(x => x.ProductInstance)
   .WithOptionalPrincipal(x => x.Sale)
   .Map(a => a.MapKey("SaleId"));
Run Code Online (Sandbox Code Playgroud)