无法翻译 LINQ 表达式 - C#

LINQ Expression cannot be translated - C#

我写了简单的查询(问题是当我尝试在 ProductCode 下面设置 Address 时):

 var query = _connectDBContext.Products
                            .Join(_context.CustomerRelations,
                                Product => Product.ForeignKeyId,
                                CustomerRelation => CustomerRelation.CompanyId,
                                (Product, CustomerRelation) => new { Product, CustomerRelation })
                            .Select(x => new ProductDto
                            {
                                Title = x.Product.Title,
                                ProductCode = x.Product.Code,
                                Address = Map(x.Product.Addresses.OrderBy(x=> x.CreatedDate).FirstOrDefault()),
                                //Address = new AddressDTO // THIS WORKS BUT LOOKS UGLY :(
                                //{
                                //    Address = x.Product.Addresses.OrderBy(x => x.CreatedDate).FirstOrDefault().Address,
                                //    Country = x.Product.Addresses.OrderBy(x => x.CreatedDate).FirstOrDefault().Country,
                                //    Zip = x.Product.Addresses.OrderBy(x => x.CreatedDate).FirstOrDefault().Zip,
                                //},
                               
                            })
                            .Where(x => x.Id == x.CustomerRelationId);

           // Rest of the code
        }

private AddressDTO Map(Address address)
{
    return new AddressDTO
    {
        Address = address.Address,
        Country = address.Country,
        Zip = address.Zip,

    };
}

上面的代码在这一行中断:

Address = Map(x.Product.Addresses.OrderBy(x=> x.CreatedDate).FirstOrDefault()),

它说linq无法翻译,建议我重写一个查询..

但是这里的注释代码几乎与 works 相同,所以如果我在 中删除调用 Map 方法Select,如果我在 Select 中取消注释这段代码,一切都会正常,但我想摆脱这个 - 写太多 OrderBy 对于每个道具,我想订购一次,然后我想使用它..但不幸的是我不知道如何.. :

//Address = new AddressDTO 
//{
//    Address = x.Product.Addresses.OrderBy(x => x.CreatedDate).FirstOrDefault().Address,
//    Country = x.Product.Addresses.OrderBy(x => x.CreatedDate).FirstOrDefault().Country,
//    Zip = x.Product.Addresses.OrderBy(x => x.CreatedDate).FirstOrDefault().Zip,
//},

提前致谢, 干杯

据推测,Entity Framework 正在将此代码翻译成 SQL,而您的自定义 Map() 方法对 SQL 是未知的。幸运的是,该方法的作用不大,因此您应该能够将其功能直接移动到查询中。

您可以使用 .Select() 将集合投射到新类型中(就像您已经为构建 ProductDto 所做的那样)。

例如:

//...
Address = x.Product.Addresses.OrderBy(x=> x.CreatedDate)
                             .Select(x=> new AddressDTO
                             {
                                 Address = x.Address,
                                 Country = x.Country,
                                 Zip = x.Zip
                             })
                             .FirstOrDefault()
//...

请参阅上面 David 的回答以了解它为何不起作用。

解决方法是,您可以在映射之前调用 .ToList(),以便在服务器上执行查询:

_connectDBContext.Products
  .Join(...)
  .Where(x => x.Id == x.CustomerRelationId)
  .ToList() // !!!
  .Select(x => new ProductDto
     {
        Title = x.Product.Title,
        ProductCode = x.Product.Code,
        Address = Map(x.Product.Addresses.OrderBy(x=> x.CreatedDate).FirstOrDefault()),
...
     });
                        

您不能按原样调用 Map 函数,但您可以稍微修改它以在 Queryables 上工作

var query = _connectDBContext.Products
                            .Join(_context.CustomerRelations,
                                Product => Product.ForeignKeyId,
                                CustomerRelation => CustomerRelation.CompanyId,
                                (Product, CustomerRelation) => new { Product, CustomerRelation })
                            .Select(x => new ProductDto
                            {
                                Title = x.Product.Title,
                                ProductCode = x.Product.Code,
                                Address = Map(x.Product.Addresses),
                               
                            })
                            .Where(x => x.Id == x.CustomerRelationId);

           // Rest of the code
        }

private AddressDTO Map(IQueryable<Address> addresses)
{
    return addresses.OrderBy(x => x.CreatedDate).Select(x => new AddressDTO
    {
        Address = address.Address,
        Country = address.Country,
        Zip = address.Zip
    }).FirstOrDefault();
}