简体   繁体   English

实体框架 - 在子实体条件下过滤和检索子实体

[英]Entity Framework - filtering and retrieving child entities on child entity condition

My problem is as follows: I have a Product entity which looks like this:我的问题如下:我有一个Product实体,如下所示:

public int Id { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public string Excerpt { get; set; }
public string Description { get; set; }
public virtual Category Category { get; set; }
public DateTime Published { get; set; }
public string[] Tags { get; set; }
public int PublisherId { get; set; }
public virtual User Publisher { get; set; }
public virtual ICollection<MyImage> Images { get; set; }

Now this Product entity can have many Images (as a child entity) which looks as follows:现在这个Product实体可以有许多Images (作为一个子实体),如下所示:

public int Id { get; set; }
public string Description { get; set; }
public DateTime DateAdded { get; set; }
public bool IsMain { get; set; }
public byte[] Image { get; set; }
public virtual Product Product { get; set; }
public int ProductId { get; set; }

So, I've got a controller route, where I would like to retrieve all the products and only those images, which are main product images (most of the time, it's going to be only a single image, but I still prefer to return a list of them).所以,我有一个 controller 路线,我想检索所有产品,只有那些图像,它们是主要产品图像(大多数时候,它只是一个图像,但我仍然更喜欢返回它们的列表)。

Currently, what I am trying to do, does not work:目前,我正在尝试做的事情不起作用:

public async Task<PagedList<Product>> GetProducts(UserParams userParams)
{
     var productsFromRepo = context.Products
         .Select(p => new {
             Product = p,
             Images = p.Images.Where(i => i.IsMain)
         })
         .OrderByDescending(b => b.Product.Published);

     var productsToReturn = productsFromRepo.Select(i => i.Product).AsQueryable();
     return await PagedList<Product>.CreateAsync(productsToReturn, userParams.PageNumber, userParams.PageSize);
}

I try to get all products, and their main image.我尝试获取所有产品及其主要图像。 And return a product with it's main image, and not all images.并返回带有主图像的产品,而不是所有图像。 As you can see, I am returning a PagedList object, where I need to pass an IQueryable as first parameter of CreateAsync method.如您所见,我返回了一个PagedList object,其中我需要传递一个IQueryable作为CreateAsync方法的第一个参数。

The thing is, I managed to do the filtering on my anonymously projected object ( productsFromRepo ).问题是,我设法对匿名投影的 object ( productsFromRepo ) 进行了过滤。 But I can not figure out how to return that anonymous object as product object with filtered Images list.但我不知道如何将匿名 object 作为产品 object 与过滤图像列表返回。

It's always returning all images, not filtered how I need.它总是返回所有图像,而不是按我的需要过滤。

In this problem, I must have my lastly projected object, in this case productsToReturn to be an IQueryable object.在这个问题中,我必须有我最后预测的 object,在这种情况下productsToReturn是一个IQueryable object。

In my project, I am using lazy loading.在我的项目中,我使用延迟加载。 So all child entities are lazy loaded by default.所以默认情况下所有子实体都是延迟加载的。

So basically, what I get now is:所以基本上,我现在得到的是:

[
    {
        "id": 2,
        "title": "My First Product",
        "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
        "category": "Uncategorized",
        "price": 15.0,
        "excerpt": "Lorem ipsum",
        "tags": [
            "Tag1",
            "Tag2"
        ],
        "images": [
            {
                "id": 1,
                "description": "test",
                "isMain": true,
                "dateAdded": "2020-07-15T22:40:09.285481",
                "image":"/9j/...."
            },
            {
                "id": 2,
                "description": "test1",
                "isMain": false,
                "dateAdded": "2020-07-15T23:15:44.74166",
                "image":"/9j/...."
            },
            {
                "id": 3,
                "description": "test1",
                "isMain": false,
                "dateAdded": "2020-07-15T23:27:39.636685",
                "image":"/9j/...."
            }
        ],
        "published": "2020-07-15T22:39:27.89482",
        "publisher": {
            "id": 1,
            "name": null,
            "lastName": null,
            "email": "testemail@gmail.com"
        }
    }
]

And what i need is:需要的是:

[
    {
        "id": 2,
        "title": "My First Product",
        "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
        "category": "Uncategorized",
        "price": 15.0,
        "excerpt": "Lorem ipsum",
        "tags": [
            "Tag1",
            "Tag2"
        ],
        "images": [
            {
                "id": 1,
                "description": "test",
                "isMain": true,
                "dateAdded": "2020-07-15T22:40:09.285481",
                "image":"/9j/...."
            },
        ],
        "published": "2020-07-15T22:39:27.89482",
        "publisher": {
            "id": 1,
            "name": null,
            "lastName": null,
            "email": "testemail@gmail.com"
        }
    }
]

Thanks in advance提前致谢

Instead of selecting on products, try selecting on the images:不要选择产品,而是尝试选择图像:

public async Task<PagedList<Product>> GetProducts(UserParams userParams)
{
     var productsFromRepo = context.Images
         .Where(i => i.IsMain)
         .Select(i => new Product {
             Id = i.Product.Id,
             Title = i.Product.Title,
             ...
             Images = new List<Image>{ i }
         })
         .OrderByDescending(b => b.Published)
         .AsQuerable();

     return await PagedList<Product>.CreateAsync(productsFromRepo, userParams.PageNumber, userParams.PageSize);
}

Well, the anonymous object doesn't help in my opinion.好吧,在我看来,匿名的 object 并没有帮助。 You can either filter the product's pictures after you retrieve it from the database, or use Query Filter if you want to stop EF from bringing it from the database.您可以在从数据库中检索产品图片对其进行筛选,或者如果您想阻止 EF 从数据库中获取产品图片,则可以使用查询筛选器

Check this documentation to get a clear picture.检查此文档以获得清晰的图片。

The idea is that you include the query filter in the fluent api configuration of the pictures entity:这个想法是您在图片实体的流畅 api 配置中包含查询过滤器:

builder.HasQueryFilter(p => p.IsMain);

This will stop EF from retrieving the pictures that aren't set as main, in ALL cases by default .这将阻止 EF在所有情况下默认检索未设置为主要的图片。 If you want EF to retrieve all pictures (ie in pictures index) you have to use如果您希望 EF 检索所有图片(即在图片索引中),您必须使用

.IgnoreQueryFilters()

in your query.在您的查询中。

PS I didn't include the full code snippets, if it doesn't make sense to you, ask me to demonstrate the full code. PS 我没有包含完整的代码片段,如果对您没有意义,请让我演示完整的代码。

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

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