将mysql查询中项目的嵌套列表属性映射到c#对象

Posted

技术标签:

【中文标题】将mysql查询中项目的嵌套列表属性映射到c#对象【英文标题】:Mapping nested List Property of items in mysql query to c# objects 【发布时间】:2021-06-30 12:41:08 【问题描述】:

请在这里帮助我。

我想获取产品的详细信息以及该产品的图片列表。下面的代码工作正常,但它只返回一张产品图片。我在将 mysql 查询的结果映射到 C# 对象时遇到问题。

这是我迄今为止尝试过的

        public ProductModel GetProductDetail(uint product_id)
        
            var cmd = this.MySqlDatabase.Connection.CreateCommand() as MySqlCommand;
            cmd.CommandText = @"SELECT products.*, images.* FROM products LEFT JOIN images ON products.product_id= images.product_id WHERE products.product_id = @product_id LIMIT 0,1";
            cmd.Parameters.AddWithValue("@product_id", product_id);
            using (var reader = cmd.ExecuteReader())
                while (reader.Read())
                
                    return new ProductModel()
                    
                        product_id = reader.GetValue<UInt32>("product_id"),
                        subcategory_id = reader.GetValue<UInt32>("subcategory_id"),
                        product_name = reader.GetValue<String>("product_name"),
                        description = reader.GetValue<String>("description"),
                        is_recent = reader.GetValue<Boolean>("is_recent"),
                        is_popular = reader.GetValue<Boolean>("is_popular"),
                        is_available = reader.GetValue<Boolean>("is_available"),
                        price = reader.GetValue<Decimal>("price"),
                        overall_rating = reader.GetValue<Double>("overall_rating"),
                        views = reader.GetValue<UInt32>("views"),
                        people_rated = reader.GetValue<UInt32>("people_rated"),
                        date_posted = reader.GetValue<DateTime>("date_posted"),
                        Images = new List<ImagesModel>
                        
                            new ImagesModel
                            
                                imageurl = reader.GetValue<String>("imageurl"),
                                created_date = reader.GetValue<DateTime>("created_date")
                            
                        
                    ;
                
            return null;
        

下面也是我得到的 JSON 结果


    "code": 1,
    "message": "Product found",
    "document": 
        "product_id": 11,
        "subcategory_id": 22,
        "product_name": "Lead Guitar",
        "description": "Unde dolor sed natus velit omnis doloribus consequatur adipisci quos quasi laboriosam optio aut beatae; cupiditate modi animi hic non qui consequatur, natus voluptatem quae ea quia est doloremque possimus.",
        "is_recent": true,
        "is_popular": false,
        "is_available": false,
        "price": 1942.51,
        "overall_rating": 3,
        "views": 520,
        "people_rated": 350,
        "date_posted": "2005-05-08T06:21:03",
        "images": [
            
                "imageurl": "http://www.thetehad.es/but/teerted/anne/ionhe.png",
                "created_date": "2021-08-28T12:33:01"
            ,
            .
            .
            . 
            // THERE SHOULD BE MORE IMAGES HERE BUT I AM GETTING ONLY ONE
        ]
    

请问我在这里做错了什么?非常感谢任何帮助。

【问题讨论】:

为什么需要在一次查询中获取产品和图片?对于单个对象在单独查询中更高效地查询自身及其图像,这里不存在选择 N+1 问题。 【参考方案1】:

有几个问题需要指出。

问题

第一

SELECT products.*, images.* FROM products LEFT JOIN images ON products.product_id= images.product_id WHERE products.product_id = @product_id LIMIT 0,1

您的 MYSQL 查询包含LIMIT 0,1,这意味着它将只返回第一行。

对这个查询使用LEFT JOIN 不太正确,因为通过删除LIMIT 0,1,它返回1 x n 记录,其中n 是具有相同product_id 的图像记录的数量。

第二

return new ProductModel()

    Images = new List<ImagesModel>
    
        new ImagesModel
        
            imageurl = reader.GetValue<String>("imageurl"),
            created_date = reader.GetValue<DateTime>("created_date")
        
    
;

您创建new ProductModel() 并将Images 分配给List&lt;ImagesModel&gt;,该List&lt;ImagesModel&gt; 仅包含一个ImagesModel 对象

解决方案

对于第一个问题:将查询一分为二并使用两个 DataReader:

第一个 DataReader 将仅根据 ProductID 查询 Product 记录 第二个DataReader会根据ProductID查询Image记录

对于第二个问题:从第二个 DataReader 检索图像记录并使用循环创建图像对象

public ProductModel GetProductDetail(uint product_id)

    ProductModel product = null;

    using (var productCmd = this.MySqlDatabase.Connection.CreateCommand() as MySqlCommand)
    
        productCmd.CommandText = @"SELECT * FROM products WHERE product_id = @product_id";
        productCmd.Parameters.Add("@product_id", SqlDbType.int).Value = product_id;

        using (var reader = productCmd.ExecuteReader())
        
            while (reader.Read())
            
                product = new ProductModel()
                
                    product_id = reader.GetValue<UInt32>("product_id"),
                    subcategory_id = reader.GetValue<UInt32>("subcategory_id"),
                    product_name = reader.GetValue<String>("product_name"),
                    description = reader.GetValue<String>("description"),
                    is_recent = reader.GetValue<Boolean>("is_recent"),
                    is_popular = reader.GetValue<Boolean>("is_popular"),
                    is_available = reader.GetValue<Boolean>("is_available"),
                    price = reader.GetValue<Decimal>("price"),
                    overall_rating = reader.GetValue<Double>("overall_rating"),
                    views = reader.GetValue<UInt32>("views"),
                    people_rated = reader.GetValue<UInt32>("people_rated"),
                    date_posted = reader.GetValue<DateTime>("date_posted")  
                ;
            
                  
    
           
    if (product == null)
        return null;

    var imageList = new List<ImagesModel>(); 
    using (var imageCmd = this.MySqlDatabase.Connection.CreateCommand() as MySqlCommand)
    
        imageCmd.CommandText = @"SELECT * FROM images WHERE product_id = @product_id";
        imageCmd.Parameters.Add("@product_id", SqlDbType.int).Value = product_id;

        using (var reader = imageCmd.ExecuteReader())
        
            while (reader.Read())
            
                imageList.Add(new ImagesModel
                
                    imageurl = reader.GetValue<String>("imageurl"),
                    created_date = reader.GetValue<DateTime>("created_date")
                );
            
                  
    
    
    product.Images = imageList;    
    return product;

【讨论】:

非常令人印象深刻。竖起大拇指!!!还有一个问题,单独查询有没有性能问题? 嗨@Pat,不客气。没有测试代码,但总体而言,提到的这些概念可以帮助您理解问题并制定解决问题的指南。希望您尽快找到解决方案。谢谢。 它就像魔术一样工作。你的回答让整个过程超级清晰

以上是关于将mysql查询中项目的嵌套列表属性映射到c#对象的主要内容,如果未能解决你的问题,请参考以下文章

使用映射库将嵌套对象映射到 C# 中的自定义对象

RestKit:将嵌套数组映射到对象

带有嵌套列表的 jOOQ 查询

使用 LINQ 根据 C# 中的属性值搜索嵌套在另一个列表中的列表中的项目?

如何使用 linq 查询具有嵌套列表的对象?

将 JSON 对象映射到 C# 类属性数组