我正在使用Linq到Sql并且有一个不会生成类的存储过程。存储过程将多个表中的数据绘制到平面文件结果集中。
返回的数据量必须尽可能小,需要限制到Sql Server的往返次数,并且必须限制服务器端处理的数量,因为这是针对ASP.NET MVC项目的
所以,我正在尝试将Linq写入Sql Query,但是我很难复制并限制返回的数据。
这是我想要转换的存储过程:
SELECT AdShops.shop_id as ID, Users.image_url_75x75, AdShops.Advertised,
Shops.shop_name, Shops.title, Shops.num_favorers as hearts, Users.transaction_sold_count as sold,
(select sum(L4.num_favorers) from Listings as L4 where L4.shop_id = L.shop_id) as listings_hearts,
(select sum(L4.views) from Listings as L4 where L4.shop_id = L.shop_id) as listings_views,
L.title AS listing_title, L.price as price, L.listing_id AS listing_id, L.tags, L.materials, L.currency_code,
L.url_170x135 as listing_image_url_170x135, L.url AS listing_url, l.views as listing_views, l.num_favorers as listing_hearts
FROM AdShops INNER JOIN
Shops ON AdShops.shop_id = Shops.shop_id INNER JOIN
Users ON Shops.user_id = Users.user_id INNER JOIN
Listings AS L ON Shops.shop_id = L.shop_id
WHERE (Shops.is_vacation = 0 AND
L.listing_id IN
(
SELECT listing_id
FROM (SELECT l2.user_id , l2.listing_id, RowNumber = ROW_NUMBER() OVER (PARTITION BY l2.user_id ORDER BY NEWID())
FROM Listings l2
INNER JOIN (
SELECT user_id
FROM Listings
GROUP BY
user_id
HAVING COUNT(*) >= 3
) cnt ON cnt.user_id = l2.user_id
) l2
WHERE l2.RowNumber <= 3 and L2.user_id = L.user_id
)
)
ORDER BY Shops.shop_name
现在,到目前为止,我可以返回一个平面文件,但无法限制列表的数量。这就是我被困住的地方:
Dim query As IEnumerable = From x In db.AdShops
Join y In (From y1 In db.Shops
Where y1.Shop_name Like _Search + "*" AndAlso y1.Is_vacation = False
Order By y1.Shop_name
Select y1) On y.Shop_id Equals x.shop_id
Join z In db.Users On x.user_id Equals z.User_id
Join l In db.Listings On l.Shop_id Equals y.Shop_id
Select New With {
.shop_id = y.Shop_id,
.user_id = z.user_id,
.listing_id = l.Listing_id
} Take 24 ' Fields ommitted for briefity...
我假设每个商店选择一个随机的3个列表,我需要使用lambda表达式,但不知道如何做到这一点。此外,需要在某个地方添加合并的总计,以便针对各个商店列出fieelds ......
有人有任何想法吗?
更新:
以下是我正在考虑的当前解决方案:
Public Class NewShops Public Property Shop_id As Integer Public Property listing_id As Integer Public Property tl_listing_hearts As Integer? Public Property tl_listing_views As Integer? Public Property listing_creation As Date End Class
Using db As New Ads.DB(Ads.DB.Conn) Dim query As IEnumerable(Of IGrouping(Of Integer, NewShops)) = (From x In db.AdShops Join y In (From y1 In db.Shops Where (y1.Shop_name Like _Search + "*" AndAlso y1.Is_vacation = False) Select y1 Skip ((_Paging.CurrentPage - 1) * _Paging.ItemsPerPage) Take (_Paging.ItemsPerPage)) On y.Shop_id Equals x.shop_id Join z In db.Users On x.user_id Equals z.User_id Join l In db.Listings On l.Shop_id Equals y.Shop_id Join lt In (From l2 In db.Listings _ Group By id = l2.Shop_id Into Hearts = Sum(l2.Num_favorers), Views = Sum(l2.Views), Count() _ Select New NewShops With {.tl_listing_views = Views, .tl_listing_hearts = Hearts, .Shop_id = id}) On lt.Shop_id Equals y.Shop_id Select New NewShops With {.Shop_id = y.Shop_id, .tl_listing_views = lt.tl_listing_views, .tl_listing_hearts = lt.tl_listing_hearts, .listing_creation = l.Creation, .listing_id = l.Listing_id }).GroupBy(Function(s) s.Shop_id).OrderByDescending(Function(s) s(0).tl_listing_views) Dim Shops as New Dictionary(Of String, List(Of NewShops)) For Each item As IEnumerable(Of NewShops) In query Shops.Add(item(0).shop_name, (From i As NewShops In item Order By i.listing_creation Descending Select i Take 3).ToList) Next End Using
有人有任何其他建议吗?
答案 0 :(得分:1)
从SQL和代码的外观来看,我不会把它变成LINQ查询。它只会模糊逻辑,可能需要几天时间才能使其正确。
如果SQLMetal没有正确生成它,您是否考虑过使用ExecuteQuery的DataContext方法返回您所追踪的项目列表?
假设您尝试转换的sproc称为sp_complicated,并且接受一个参数,类似下面的内容应该可以解决这个问题
Protected Class TheResults
Public Property ID as Integer
Public Property image_url_75x75 as String
'... and so on and so forth for all the returned columns. Be careful with nulls
End Class
'then, when you want to use it
Using db As New Ads.DB(Ads.DB.Conn)
dim results = db.ExecuteQuery(Of TheResults)("exec sp_complicated {0}", _Search)
End Using
在您惊慌失措之前,不易受SQL注入影响。 L2SQL uses proper SQLParameters,只要你使用波浪形,而不是自己连接弦。