为什么我的查询无法在EF中加载相关数据?

时间:2019-03-17 23:34:47

标签: c# entity-framework linq

我是EF和linq的初学者。 我的模型包括产品/产品类型/参数/产品参数表。我在通过Include()方法使用紧急加载来加载数据时遇到一些困难。我需要从4个表中获取相关数据:fieldes产品-> fielde产品类型名称-> fielde参数名称-> fielde产品参数值

模型和DTO:

 public class Product 
{
    public long ProductId { get; set; }

    public string Name { get; set; }
    public string Number { get; set; }
    public double Amount { get; set; }
    public double PrimeCostEUR { get; set; }

    public long ProductTypeId {  get; set; }
    public ProductType ProductType { get; set; }

    public ICollection<ProductParameter> ProductParameters { get; set; } = 
    new List<ProductParameter>();
}

public class ProductType 
{
    public long ProductTypeId { get; set; }
    public string NameType { get; set; }

    public ICollection<Product> Products { get; set; }
    public ICollection<Parameter> Parameters { get; set; }

}
public class Parameter 
{
    public long ParameterId { get; set; }
    public string Name { get; set; }

    public long ProductTypeId { get; set; }
    public ProductType ProductType { get; set; }

    public ICollection<ProductParameter> ProductParameters { get; set; } = 
    new List<ProductParameter>();
}

 public class ProductParameter 
{
    public long ProductParameterId { get; set; }

    public long ProductId { get; set; }
    public long ParameterId { get; set; }

    public Parameter Parameter { get; set; }
    public Product Product { get; set; }

    public string Value { get; set; }
}

public class ProductDTO
{
    public long ProductId { get; set; }
    public string Number { get; set; }
    public double Amount { get; set; }
    public double PrimeCostEUR { get; set; }

    public long ProductTypeId { get; set; }
    public string NameType { get; set; }

    public long ParameterId { get; set; }
    public string Name { get; set; }

    public long ProductParameterId { get; set; }
    public string Value { get; set; }

}

这是我的方法

public async Task<IEnumerable<ProductDTO>> GetProducts()
    {
       var items = await _context.Products
           .Include(t => t.ProductType)
                   .ThenInclude(p => p.Parameters)
                   .ThenInclude(pp => pp.ProductParameters)
            .Include(t => t.ProductParameters)
            .Select(p => new ProductDTO
             {
               ProductId = p.ProductId,
               Number = p.Number,
               Amount = p.Amount,
               PrimeCostEUR = p.PrimeCostEUR,
               NameType = p.ProductType.NameType,
               ProductTypeId = p.ProductTypeId,
               Name = p.Parameter.Name,
               Value = p.ProductParameter.Value
             })
              .Where(p => p.ProductTypeId == 1)
               .ToListAsync();
        return items;
 }

这是我遇到的错误:

  

错误CS1061'产品'不包含'参数'/'产品参数'的定义,并且找不到可以接受的扩展方法'参数'接受类型为'产品'的第一个参数(您是否缺少using指令或组装参考?

1 个答案:

答案 0 :(得分:1)

Include仅执行急切的加载,在执行Select操作时不是必需的。从我的角度来看,如果您尝试从Product实体加载Parameter和ProductParameter,并且您提供的代码甚至都不应编译,并且该实体没有任何引用。

首先要看的是您的实体关系。查看您的对象模型,您似乎在Product和ProductType之间具有多对一的关系,然后在ProductParameter表的帮助下,在Product和Parameter之间具有多对多的关系。在ProductType上也有一个Parameters集合,我对此相当怀疑。处理关系时,我建议默认情况下使用单向引用,并且仅在需要时才启用双向引用。例如,一个产品需要引用一个产品类型,但是,产品类型真的需要引用该类型的所有产品吗? (如果需要,可以通过从Product进行查询,我们仍然可以做到这一点)更少的双向引用更易于使用。

要获取产品DTO,您需要解决DTO是代表产品(带有参数)还是单个产品和参数的组合。一个产品具有多个参数,因此,如果DTO代表单个产品,则该DTO将需要处理一组参数。如果DTO表示产品和参数的组合,那么具有3个相关参数的产品将导致创建3个DTO。

对于第二种情况,考虑到您当前拥有的DTO结构,您将需要查看类似于以下内容的Linq查询:

   var items = await _context.Products
        .SelectMany(p => p.ProductParameters)
        .Select(pp => new ProductDTO
         {
           ProductId = pp.ProductId,
           Number = pp.Product.Number,
           Amount = pp.Product.Amount,
           PrimeCostEUR = pp.Product.PrimeCostEUR,
           NameType = pp.Product.ProductType.NameType,
           ProductTypeId = pp.Product.ProductTypeId,
           Name = pp.Parameter.Name,
           Value = pp.Value
         })
          .Where(pp => pp.Product.ProductTypeId == 1)
          .ToListAsync();
    return items;

查询将针对ProductParameters运行,以访问产品和每个参数以及产品参数值。