简体   繁体   English

ASP.NET 内核 Web API:异步任务有问题?

[英]ASP.NET Core Web API: having trouble with async task?

I am working on a ASP.NET Core Web API project and I want the controllers return results asynchronously.我正在研究 ASP.NET 核心 Web API 项目,我希望控制器异步返回结果。 But I am having problems with the get by id call.但是我在通过 id 调用时遇到问题。

Models:楷模:

public class Product
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string ProductType { get; set; }

    [Required]
    [MaxLength(250)]
    public string ProductDescription { get; set; }

    [Required]
    public int ProductCategory { get; set; }

    //Navigation Properties
    public int TravelPackageId { get; set; }
    public TravelPackage TravelPackage { get; set; }
}

public class TravelPackage
{
    [Key]
    public int Id { get; set; }

    [Required]
    [MaxLength(50)]
    public string PackageName { get; set; }

    //Navigation Properties
    public List<Product> Products { get; set; }
}

TravelPackage has a list of products. TravelPackage有一个产品列表。 When I make a call to a travelPackage by id, I need that list of products be returned too.当我通过 id 调用travelPackage时,我也需要返回该产品列表。

This is my repository for both call (all travelPackages and specific travelPackage by id)这是我的两个调用的存储库(所有travelPackages和特定的travelPackage by id)

public class TravelPackageRepository : ITravelPackageRepository
{
    private readonly DataContext _context;

    public TravelPackageRepository(DataContext context)
    {
        _context = context;
    }

    public async Task<TravelPackage> GetProductByIdAsync(int id)
    {
        return await _context.TravelPackages.Include(t => t.Products.Select(p => new
        {
            Id = t.Id,
            PackageName = t.PackageName,
            Products = t.Products.Select(product => new Product()
            {
                Id = product.Id,
                ProductType = product.ProductType,
                ProductDescription = product.ProductDescription,
                ProductCategory = product.ProductCategory,
                TravelPackageId = product.TravelPackageId
            })
        })).FirstAsync(t => t.Id == id);
     
    }

    public async Task<System.Collections.Generic.IReadOnlyList<TravelPackage>> GetTravelPackagesAsync()
    {
        return await _context.TravelPackages
            .Include(x => x.Products)
            .ThenInclude(x => x.TravelPackage)
            .ToListAsync();
    }
}

But I am getting the following error:但我收到以下错误:

System.InvalidOperationException: The expression 't.Products.AsQueryable().Select(p => new <>f__AnonymousType2`3(Id = t.Id, PackageName = t.PackageName, Products = t.Products.AsQueryable().Select(product => new Product() { Id = product.Id, ProductType = product.ProductType, ProductDescription = product.ProductDescription, ProductCategory = product.ProductCategory, TravelPackageId = product.TravelPackageId})))' is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'. System.InvalidOperationException:表达式 't.Products.AsQueryable().Select(p => new <>f__AnonymousType2`3(Id = t.Id, PackageName = t.PackageName, Products = t.Products.AsQueryable().Select (product => new Product() { Id = product.Id, ProductType = product.ProductType, ProductDescription = product.ProductDescription, ProductCategory = product.ProductCategory, TravelPackageId = product.TravelPackageId})))' 在“包含”内无效操作,因为它不代表属性访问:'t => t.MyProperty'。 To target navigations declared on derived types, use casting ('t => ((Derived)t).MyProperty') or the 'as' operator ('t => (t as Derived).MyProperty').要定位在派生类型上声明的导航,请使用强制转换 ('t => ((Derived)t).MyProperty') 或 'as' 运算符 ('t => (t as Derived).MyProperty')。 Collection navigation access can be filtered by composing Where, OrderBy(Descending), ThenBy(Descending), Skip or Take operations.集合导航访问可以通过组合 Where、OrderBy(Descending)、ThenBy(Descending)、Skip 或 Take 操作进行过滤。

Before implementing the repository and async/await, this was my controller for travelPackages and it worked fine:在实现存储库和 async/await 之前,这是我的用于 travelPackages 的 controller,它运行良好:

[HttpGet("{id}")]
public  ActionResult<TravelPackage> GetTravelPackage(int id)
{
        var item = _context.TravelPackages.Where(package => package.Id == id).Select(package => new
        {
            Id= package.Id,
            PackageName =package.PackageName,
            Products = package.Products.Select(product => new Product()
            {
                Id = product.Id,
                ProductType = product.ProductType,
                ProductDescription = product.ProductDescription,
                ProductCategory = product.ProductCategory,
                TravelPackageId = product.TravelPackageId
            })
        });

        return Ok(item);
}

I do not have much experience working with .net core, async/await tasks and linq, so I am not sure how to deal with this error.我没有太多使用 .net 内核、异步/等待任务和 linq 的经验,所以我不知道如何处理这个错误。

Thanks谢谢

The error is caused by this:该错误是由以下原因引起的:

_context.TravelPackages.Include(t => t.Products.Select

The Include statement should represent a property access but you are selecting to an anonymous object within the Include. Include 语句应表示属性访问,但您选择的是 Include 中的匿名 object。

In this case, the navigation property is Products so change it to:在本例中,导航属性为 Products,因此将其更改为:

_context.TravelPackages.Include(t => t.Products).Select

This has a closing bracket after the Products navigation property.在 Products 导航属性之后有一个右括号。 So you are then including Product and the select query follows this.因此,您将包括 Product 并且 select 查询如下。

As JMP noticed there is a syntax error. JMP 注意到存在语法错误。 But also you are trying to return an anonymous object.但是你也试图返回一个匿名的 object。 So try this:所以试试这个:

 return await _context.TravelPackages
    .Where(package => package.Id == id)
    .Select(t => 
     new TravelPackage
        {
            Id = t.Id,
            PackageName = t.PackageName,
            Products = t.Products.Select(product => new Product()
            {
                Id = product.Id,
                ProductType = product.ProductType,
                ProductDescription = product.ProductDescription,
                ProductCategory = product.ProductCategory,
                TravelPackageId = product.TravelPackageId
            })
        }).FirstOrDefaultAsync();

but since you are including all properties, you can make it shorter:但由于您包含所有属性,您可以缩短它:

return await _context.TravelPackages
    .Include(t => t.Products)
    .Where(package => package.Id == id)
    .FirstOrDefaultAsync();

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

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