简体   繁体   English

EF Core 多对多查询连接 3 个表

[英]EF Core Many to Many Querying to join 3 tables

I have the following Code:我有以下代码:

public class ProductTbl
{
    public override int Id { get; set; }
    public string ProductName { get; set; }
    public List<ProductManufacturer> ProductManufacturer { get; set; } //M2M
}

public class Manufacturer_LKP
{
    public override int Id { get; set; }
    public string ManufacturerName { get; set; }
    public List<ProductManufacturer> ProductManufacturer { get; set; } //M2M
}

public class ProductManufacturer
{
    public ProductTbl Product { get; set; }
    public int ProductID { get; set; }
    public Manufacturer_LKP Manufacturer { get; set; }
    public int ManufacturerID { get; set; }
}
  public class SupplierTbl
{
    public  int SupplierID { get; set; }
    public string SupplierName { get; set; }

}

public class ProductSuppliertbl 
{
    public  int Id { get; set; }
    public ProductTbl Product { get; set; }
    public int ProductID { get; set; }
    public SuppilerTbl Supplier { get; set; }
    public int SupplierID { get; set; }
}

* I need to write Linq query to join all 3 tables (Product,Manufacture,ProductManufacturer) to get ProductName and ManufatureName together in one DB trip *我需要编写 Linq 查询来连接所有 3 个表(Product、Manufacture、ProductManufacturer),以便在一次 DB 行程中同时获取 ProductName 和 ManufatureName
*When I do the following I missed the Manufacture object (Manufacture=Null) *当我执行以下操作时,我错过了 Manufacture 对象(Manufacture=Null)

DbSet<ProductTbl>()
    .Where(a => a.Id == 5)
    .AsNoTracking()
    .Include(a => a.ProductType)
    .Include(a => a.ProductManufacturer)

Above Linq Just joint Product table with ProductManufacture Table So I cannot Get "ManufactureName"以上 Linq 只是将 Product 表与 ProductManufacture 表联合起来,所以我无法获得“ManufactureName”

So Is there is any way to join the 3 tables to get ManufactureName beside the ProductName in one DB trip?那么有没有什么办法可以在一次 DB 行程中加入 3 个表以在 ProductName 旁边获得 ManufactureName ?

try this尝试这个

var list = context.Set<ProductManufacturer>()
    .Select(i => new
    {
       ProductName = i.Product.ProductName,
       ManufacturerName = i.Manufacturer.ManufacturerName
    })
    .ToList();

Projection is your friend when trying to load related data.尝试加载相关数据时,投影是您的朋友。 The issue with many-to-many is that you are saying a product has many manufacturers, while at the same time it has many suppliers多对多的问题是你说一个产品有很多制造商,同时它有很多供应商

The Product would need a reference to the ProductSuppliers for that product to easily manage the many suppliers requirement.产品需要引用该产品的 ProductSuppliers 以轻松管理众多供应商的需求。

var productData = context.Products
    .Select(p => new 
    {
        p.ProductName,
        ManufacturerNames = p.ProductManufacturers.Select(pm => pm.Manufacturer.ManufacturerName).ToList(),
        SupplierNames = x.ProductSuppliers.Select(ps => ps.Supplier.SupplierName).ToList()
    }).ToList();

This gives you a list of products, with each product's associated manufacturer names and supplier names.这为您提供了一个产品列表,其中包含每个产品的相关制造商名称和供应商名称。 With that data you can format output how you see fit.使用这些数据,您可以按照您认为合适的方式格式化输出。

If you want the entities themselves, then the missing bit is ThenInclude :如果您想要实体本身,那么缺少的位是ThenInclude

var products = context.Products
    .Include(p => p.ProductManufacturers)
    .ThenInclude(pm => pm.Manufacturer)
    .Include(p => p.ProductSuppliers)
    .ThenInclude(ps => ps.Supplier)
    .AsNoTracking()
    .ToList();

This would load the entire entity graph.这将加载整个实体图。

If you don't want or cannot put a ProductSuppliers collection in product then you can build the query entirely from the ProductSupplier, but it's a bit messier.如果您不想或不能在产品中放置 ProductSuppliers 集合,那么您可以完全从 ProductSupplier 构建查询,但它有点混乱。

If you are using EF Core 5 and your joining entities (ProductManufacturer/ProductSupplier) are just simply the FK references to their respective entities, then you can do away with the joining entity and let EF manage it behind the scenes.如果您使用的是 EF Core 5 并且您的加入实体 (ProductManufacturer/ProductSupplier) 只是对其各自实体的 FK 引用,那么您可以取消加入实体并让 EF 在幕后管理它。 Product would just contain a collection of Manufacturers and a collection of Suppliers.产品将只包含制造商的集合和供应商的集合。 These can be configured still with a HasMany..WithMany , but makes queries a lot cleaner to look at without the intermediate entities.这些仍然可以使用HasMany..WithMany进行配置,但在没有中间实体的情况下使查询更加清晰。

Ie IE

var productData = context.Products
    .Select(p => new 
    {
        p.ProductName,
        ManufacturerNames = p.Manufacturers.Select(m => m.ManufacturerName).ToList(),
        SupplierNames = x.Suppliers.Select(s => ps.SupplierName).ToList()
    }).ToList();

and

var products = context.Products
    .Include(p => p.Manufacturers)
    .Include(p => p.Suppliers)
    .AsNoTracking()
    .ToList();

... respectively. ... 分别。 Intermediate joining entities are only needed if there are additional properties you want to access in the joining entity.仅当您希望在加入实体中访问其他属性时,才需要中间加入实体。 (Ie CreatedBy/At, etc.) (即 CreatedBy/At 等)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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