我有一个OData Web服务,就访问和返回数据库数据而言,它主要是OOTB。
我们看到的问题是,生成的代码非常复杂,不必要地复杂,并且在对服务器执行时会导致巨大的延迟。
例如:
SELECT [Extent1].[Id] AS [Id], N'ODATAModel.LatestFiguresView' AS [C1], N'EntityType,Name,RegistrationNumber,OfficeNumber,DateRegistered,...,Id' AS [C2], [Extent1].[EntityType] AS [EntityType], [Extent1].[Name] AS [Name], [Extent1].[RegistrationNumber] AS [RegistrationNumber], [Extent1].[OfficeNumber] AS [OfficeNumber], ... Loads of other columns ... , N'' AS [C12] FROM (SELECT [LatestFiguresView].[Id] AS [Id], [LatestFiguresView].[EntityType] AS [EntityType], [LatestFiguresView].[Name] AS [Name], [LatestFiguresView].[RegistrationNumber] AS [RegistrationNumber], [LatestFiguresView].[OfficeNumber] AS [OfficeNumber], ... Loads of those same columns ... FROM [dbo].[LatestFiguresView] AS [LatestFiguresView]) AS [Extent1] WHERE (N'Registered' = [Extent1].[RegistrationStatus]) AND ((1 = [Extent1].[Reservation]) OR (1 = (CASE WHEN ([Extent1].[Name] LIKE N'%White%') THEN cast(1 as bit) WHEN ( NOT ([Extent1].[Name] LIKE N'%White%')) THEN cast(0 as bit) END)) OR (1 = (CASE WHEN ([Extent1].[Sectors] LIKE '%Business%') THEN cast(1 as bit) WHEN ( NOT ([Extent1].[Sectors] LIKE '%Business%')) THEN cast(0 as bit) END)) OR ((1 = (CASE WHEN ... etc, etc ... END))))
如您所见,没有不必要的嵌套选择,并且WHERE子句包含对值的冗余检查负载(例如 “ CASE WHEN MyColumn LIKE’%Value%’THEN 1 WHEN NOT MyColumn LIKE’%Value%’THEN 0” )
当然,有一种方法可以解决这种混乱,以防它击中数据库?
当您使用Entity Framework从数据库中选择一个大型对象图时,您会收到-如所看到的- 通过将多个查询表连接在一起形成的大量数据。然后,当将超大结果集剥离并切回到实体中时,“魔术”就会再次出现在您的应用程序中。
您映射的每一列都将从数据库中选择。这是自然的- 您不能选择实体的一半。如果您选择,LatestFiguresView则该视图中的每一列都将出现在您的select语句中;如果您要检索某个订单上的产品,则Product&上的每个映射列Order都将出现在结果集中。
LatestFiguresView
Product
Order
是的,Entity Framework总是会做SELECT [Column] FROM (SELECT [dbo].[Column] AS [Column])。我无法告诉您原因,但是我猜想它或者在某些直接从表中选择会导致问题的边缘情况下提高代码安全性,或者使查询生成器更高效。您说得对,这些都是“不必要的”,但我认为它们不会花费任何费用。我可以运行SELECT * FROM MyTable,并SELECT * (SELECT * FROM MyTable) t在同一时间。
SELECT [Column] FROM (SELECT [dbo].[Column] AS [Column])
SELECT * FROM MyTable
SELECT * (SELECT * FROM MyTable) t
最后,WHEREandCASE语句由您的查询确定- 看不到它或完整WHERE子句,很难注释(注意:我不是很想看您的查询,我确定它不是很漂亮)。如果有的if x or y or (a & b)话,事情会变得凌乱。
WHERE
CASE
if x or y or (a & b)
我通常不担心CASE语句,因为它们在SQL中的运行速度非常快。我再次假设这是一个代码安全性决定,或者它允许使用更高效(更通用?)的查询生成器。
我建议您在查询分析器中运行此程序以对其进行基准测试并确定任何问题,然后编写自己的SQL并执行相同的操作。在很多情况下,编写存储过程比使Entity Framework编译查询更有效,但是如果直接从具有多个条件的View中进行选择是其中一种情况,我会感到惊讶。