简体   繁体   中英

One-To-One relationship with nullable foreign keys

I want to create One-To-One relationship in EF where Foreign Keys can be null (So, It can be called 0..1-to-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; }
}

FluentAPI configuration:

modelBuilder.Entity<Sale>()
   .HasOptional(x => x.ProductInstance)
   .WithOptionalPrincipal(x => x.Sale);

But it's generate two columns in table ProductInstance :

  • Sale_id - foreign key
  • SaleId

Here is generated migration code:

 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);

How can I do to get only one column SaleId which will be Foreign key?

One-to-zero-or-one relationship:

A one-to-zero-or-one relationship happens when a primary key of one table becomes PK & FK in another table in a relational database such as SQL Server.

One-to-zero-or-one with Data Annotation as follows:

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; }
}

One-to-zero-or-one with Fluent API as follows:

modelBuilder.Entity<ProductInstance>()
                .HasOptional(s => s.Sale)
                .WithRequired(ad => ad.ProductInstance);

In above case, a ProductInstance can be saved without Sale but the Sale entity cannot be saved without the ProductInstance entity. Keep in min in the above case, A ProductInstance cannot have more than one Sale .

One-to-One relationship:

We can not configure a one-to-One relationship between entities where both ends are required, meaning that the ProductInstance entity object must include the Sale entity object and the Sale entity must include the ProductInstance entity object in order to save it. One-to-one relationships are technically not possible in MS SQL Server. But we can configure one-to-One relationship between entities where both ends or at least one end is optional as follows:

One-to--one with Data Annotation as follows:

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; }
}

One-to-one with Fluent API as follows:

modelBuilder.Entity<Person>()
                .HasOptional(pi => pi.Department)
                .WithMany()
                .HasForeignKey(s => s.DepartmentId);

EF does not support one-to-one associations with explicit FK property - there is no HasForeignKey fluent API and if you try to workaround it with ForeignKey data annotation, you'll get multiplicity exception during the migration.

The only solution is to remove the ProductInstance.SaleId property, ending up with model:

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; }
}

and configuration:

modelBuilder.Entity<Sale>()
   .HasOptional(x => x.ProductInstance)
   .WithOptionalPrincipal(x => x.Sale)
   .Map(a => a.MapKey("SaleId"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM