实体框架嵌套联接

时间:2019-03-23 05:58:51

标签: entity-framework .net-core

我是实体框架的新手,当我的模型看起来像这样(大大简化)时,很难弄清楚如何使用联接进行查询

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

    public Vehicles Vehicles {get; set;}   
}

class Vehicles
{
    public List<Vehicle> Items {get; set;}
}

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

    public int CustomerId {get; set;}
}

如果我将List<Vehicle>直接放在客户类别上。我可以像这样

builder.Entity<Customer>()
    .HasMany(x => x.Items)
    .WithOne()
    .HasForeignKey(x => x.CustomerId);

那我可以做到这一点,然后用车辆取回客户对象

db.Customers.Include(x => x.Items).FirstOrDefault(x => x.Id == 1);

我不了解的是如何使用原始模型集执行此操作。如果可能的话,我想保持他们的状态。我试过在我的onModelCreating方法中进行各种版本的操作,但是没有运气。

builder.Entity<Customer>(t =>
{
    t.OwnsOne(x => x.Vehicles, v =>
    {
        v.HasMany(x => x.Items).WithOne().HasForeignKey(x => x.CustomerId);
    });
});

2 个答案:

答案 0 :(得分:2)

可以映射原始类,但以与直觉相反的方式。

由于Vehicles类只是一个容器,因此按照您的尝试将其映射为拥有实体似乎是最自然的方法。但是,当前EF Core不允许拥有实体在关系的主要方面,因此您需要这样做。

因此,您需要将Vehicles类映射为与Customer共享同一表的常规“实体”,即所谓的table splitting。您必须明确地执行EF Core对所拥有实体所做的所有工作-定义一个shadow property,并且映射是与Customer一对一关系的PK和FK。您还需要显式地将Vehicle.CustomerId映射为FK,因为从EF的角度来看,VehicleVehicles而不是Custome相关,因此,传统的FK假定的属性/列名称将为VehiclesId。请注意,使用此模型,您将永远无法定义Customer的反向导航属性Vehicle

话虽如此,这是所需的流畅配置:

modelBuilder.Entity<Vehicles>(builder =>
{
    // Table
    builder.ToTable(modelBuilder.Entity<Customer>().Metadata.Relational().TableName);
    // PK
    builder.Property<int>("Id");
    builder.HasKey("Id");
    // One-to-one relationship with Customer
    builder.HasOne<Customer>()
        .WithOne(e => e.Vehicles)
        .HasForeignKey<Vehicles>("Id");
    // One-to-many relationship with Vehicle
    builder.HasMany(e => e.Items)
        .WithOne()
        .HasForeignKey(e => e.CustomerId);
});

和用法:

db.Customers
    .Include(x => x.Vehicles.Items) // <--
    // ...

答案 1 :(得分:0)

使用.Join

请参见此问题的一些示例:

Entity Framework Join 3 Tables