使用原始 SQL 查询绑定复杂模型实体?
Posted
技术标签:
【中文标题】使用原始 SQL 查询绑定复杂模型实体?【英文标题】:Binding Complex Model Entity With Raw SQL Query? 【发布时间】:2018-03-01 06:46:12 【问题描述】:我一直在使用实体框架,我可以轻松地与实体本身进行复杂的模型绑定,但是当涉及到原始 sql 绑定时,我找不到任何对关系数据库进行复杂绑定的解决方案。
例如,以下是为产品类建模代码的实体-
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 行数据(对于这个例子),图像为空,应该是 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
【问题讨论】:
也发布dynamicSearchQuery
。
好的,编辑一下
为什么这个问题要-1?
@tchelidze 我已经用更多信息编辑了这个问题
为什么? :-) (如下所述,但为了完整起见)
【参考方案1】:
你可以引入一个新的对象,例如我们称之为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% 正确,但您明白了。该技术是检索未分组的数据并将其分组回所需的结构。
【讨论】:
我也有同样的想法,但我真的想避免另一个步骤,如果实体可以自己做的话。我的意思是内置功能可以做到。我将等待替代方案的任何方式,如果没有更好的解决方案,我将接受您的回答。 这也引出了另一个问题,以防模型需要是通用的,然后呢? 1)db
是一个特定的数据上下文,它拥有所有实体、关系等的知识,但是通过使用db.Database
,您基本上离开了该级别并进入原始访问。您基本上在实体框架数据库上下文之外进行操作。 2)“unflattening”技术特定于使用的对象,通用解决方案不是您想要构建的,您不想重新发明实体框架:-) 也许,更好解决方案的来源在于 为什么,绕过EF内置函数的目的是什么?否则,这将是一条更加崎岖不平的道路。
哎呀,这将是非常崎岖的道路:P以上是关于使用原始 SQL 查询绑定复杂模型实体?的主要内容,如果未能解决你的问题,请参考以下文章
如何将参数绑定到模型上使用的 Laravel 中的原始数据库查询?