使用原始SQL查询绑定复杂模型实体?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用原始SQL查询绑定复杂模型实体?相关的知识,希望对你有一定的参考价值。

我一直在使用实体框架,我可以很容易地与实体本身进行复杂的模型绑定,但是当涉及到原始的sql绑定时,我找不到任何解决方案正在做关系db的复杂绑定。

例如,以下是为产品类建模代码的实体 -

var prodResult = db.products.Where(p => p.isActive == true).Select(p => new ComplexProductModel
                {
                    id = p.id,
                    dateCreated = p.date_created,
                    datePublished = null,
                    desc = p.product_desc,
                    images = db.products_images.Where(pi => pi.prod_id == p.id).Select(pi => pi.prod_img_thumb).ToList(),
                    summary = p.product_summary,
                    title = p.product_name + " " + p.product_code
                }).ToList();

这实现了针对复杂模型的数据,该模型根据查询要求在主复杂模型中保存列表类型的字符串或类。

现在我尝试使用原始sql执行运行相同的生成查询,但图像对象的绑定失败。

var rawComplexData = db.Database.SqlQuery<ComplexProductModel>(dynamicSearchQuery).ToList(); 

有没有针对这种情况的解决方案,我得到的是10行数据(对于这个例子),图像为null,应该是7行,重复获取的图像进入List<string> images用于ComplexProductModel

以下是用于更好地理解代码的复杂产品模型:

public ComplexProductModel {
        long? id { get; set; }
        string title { get; set; }
        string desc { get; set; }
        string summary { get; set; }
        List<string> images { get; set; }
        DateTime? datePublished { get; set; }
        DateTime? dateCreated { get; set; }
    }

根据@tchelidze请求,这里是dynamicQuery,这基本上是我从实体框架产生的东西中抓取的:

SELECT 
    [Project2].[C1] AS [C1], 
    [Project2].[id] AS [id], 
    [Project2].[date_created] AS [date_created], 
    [Project2].[C2] AS [C2], 
    [Project2].[product_desc] AS [product_desc], 
    [Project2].[product_summary] AS [product_summary], 
    [Project2].[C3] AS [C3], 
    [Project2].[C4] AS [C4], 
    [Project2].[prod_img_thumb] AS [prod_img_thumb]
    FROM ( SELECT 
        [Extent1].[id] AS [id], 
        [Extent1].[product_desc] AS [product_desc], 
        [Extent1].[product_summary] AS [product_summary], 
        [Extent1].[date_created] AS [date_created], 
        1 AS [C1], 
        CAST(NULL AS datetime2) AS [C2], 
        [Project1].[prod_img_thumb] AS [prod_img_thumb], 
        CASE WHEN ([Extent1].[product_name] IS NULL) THEN N'' ELSE [Extent1].[product_name] END + N' ' + CASE WHEN ([Extent1].[product_code] IS NULL) THEN N'' ELSE [Extent1].[product_code] END AS [C3], 
        [Project1].[C1] AS [C4]
        FROM  [dbo].[products] AS [Extent1]
        LEFT OUTER JOIN  (SELECT 
            [Extent2].[prod_id] AS [prod_id], 
            [Extent2].[prod_img_thumb] AS [prod_img_thumb], 
            1 AS [C1]
            FROM [dbo].[products_images] AS [Extent2] ) AS [Project1] ON [Project1].[prod_id] = [Extent1].[id]
        WHERE 1 = [Extent1].[isActive]
    )  AS [Project2]
    ORDER BY [Project2].[id] ASC, [Project2].[C4] ASC
答案

你可以引入一个新的对象,例如让我们称之为ComplexProductDto,它应该与查询结果结构完全匹配,因为它是从SQL返回的,例如:

// Please adjust...
public class ComplexProductDto
{
    public int Id { get; set; }
    public int ProductDesc { get; set; }
    ...
    public string ProdImgThumb { get; set; }
}

现在,数据将被展平并取消组合,包含重复记录,您可以使用Linq将其分组到内存中。

var rawComplexData = db.Database.SqlQuery<ComplexProductDto>(dynamicSearchQuery).ToList(); 
var prodResult = rawComplexData
  .GroupBy(x => new
  {
      x.Id,
      x.ProductDesc,
      // List all but Image...
  })
  .Select(x => new ComplexProductModel
  {
      id = x.Key.Id,
      desc = x,Key.ProductDesc,
      .... // etc.
      images = x.Select(i => i.ProdImgThumb).ToList()
  });

代码可能不是100%正确,但你明白了。该技术是检索未分组的数据并将其分组回所需的结构。

以上是关于使用原始SQL查询绑定复杂模型实体?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用实体框架执行原始 SQL 查询而无需使用模型?

教义:从原始 SQL 中水合模型

在 Dapper 和实体框架中处理对象的方式有啥区别 - 使用原始 SQL 查询?

在 EF6 中执行复杂的原始 SQL 查询

Mybatis复杂查询动态sql及缓存详解

Laravel 原始 SQL 查询,具有多次出现的命名绑定