尝试在LINQ中实现SQL查询

时间:2014-01-22 10:09:42

标签: c# sql linq

我正在尝试在LINQ中实现SQL查询,但我找不到出错的地方。

原始SQL命令:

SELECT DISTINCT a.art_id, a.art_title,a.art_permalink, MAX(sp.sp_code), MAX(p.pr_cat_name),  MAX(p.pr_value), MAX(p.pr_cat_id), MAX(p.pr_cat_id)
FROM vArtPart sp
JOIN vArticle a ON (sp.art_id = a.art_id)
JOIN vPrice p ON (a.art_id = p.art_id)
WHERE 
sp.sp_id = 31 AND 
a.art_visible = 1 AND
a.lng_id = 1
GROUP BY a.art_id, a.art_title, a.art_permalink

Linq查询尝试(不工作)

var q = (from sp in db.vArtParts
         where sp.sp_id == dd_type.SelectedValue.ToInt()
         join a in db.vArticles on sp.art_id equals a.art_id into aa
         from a in aa.DefaultIfEmpty()
         join p in db.vPrices on a.art_id equals p.art_id into pp
         from p in pp.DefaultIfEmpty()
         where a.art_visible == true && a.lng_id == 1
         group sp by new {a.art_id, a.art_title, a.art_permalink} into g
         select new
             {
                 art_id = (int?)g.art_id,
                 g.art_title,
                 g.art_permalink,
                 sp_code = g.Max(gg=>gg.sp_code),
                 pr_cat_name = g.Max(gg=>gg.pr_cat_name),
                 pr_value = g.Max(gg=>gg.pr_value),
                 pr_cat_id = (int?)g.Max(gg=>gg.pr_cat_id)
             }).ToList();

* upd:相同的LINQ查询在没有分组的情况下工作(但我需要这个):

var q = (from sp in db.vArtParts
                 where sp.sp_id == dd_type.SelectedValue.ToInt()
                 join a in db.vArticles on sp.art_id equals a.art_id into aa
                 from a in aa.DefaultIfEmpty()
                 join p in db.vPrices on a.art_id equals p.art_id into pp
                 from p in pp.DefaultIfEmpty()
                 where a.art_visible == true && a.lng_id == 1
                 select new
                     {
                         art_id = (int?)a.art_id,
                         a.art_title,
                         a.art_permalink,
                         sp.sp_code,
                         p.pr_cat_name,
                         p.pr_value,
                         pr_cat_id = (int?)p.pr_cat_id
                     }).ToList();

* upd:错误讯息:

  

错误CS1061:'System.Linq.IGrouping'确实如此   不包含'art_id'的定义,也没有扩展方法'art_id'   接受第一个类型的参数   可以找到'System.Linq.IGrouping'(是   你错过了使用指令或程序集引用?)

ASP.global_asax.Application_Error Error System.Web.HttpParseException (0x80004005): ***\ctrl_search_product.ascx.cs(70): error CS1061: 'System.Linq.IGrouping<AnonymousType#1,vArtPart>' does not contain a definition for 'art_id' and no extension method 'art_id' accepting a first argument of type 'System.Linq.IGrouping<AnonymousType#1,vArtPart>' could be found (are you missing a using directive or an assembly reference?) ---> System.Web.HttpCompileException (0x80004005): c:\inetpub\vhosts\domostroy-msk.ru\httpdocs\inc\ctrl_search_product.ascx.cs(70): error CS1061: 'System.Linq.IGrouping<AnonymousType#1,vArtPart>' does not contain a definition for 'art_id' and no extension method 'art_id' accepting a first argument of type 'System.Linq.IGrouping<AnonymousType#1,vArtPart>' could be found (are you missing a using directive or an assembly reference?)
   at System.Web.Compilation.BuildManager.PostProcessFoundBuildResult(BuildResult result, Boolean keyFromVPP, VirtualPath virtualPath)
   at System.Web.Compilation.BuildManager.GetBuildResultFromCacheInternal(String cacheKey, Boolean keyFromVPP, VirtualPath virtualPath, Int64 hashCode, Boolean ensureIsUpToDate)
   at System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, Boolean ensureIsUpToDate)
   at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
   at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
   at System.Web.UI.BaseTemplateParser.GetReferencedType(VirtualPath virtualPath, Boolean allowNoCompile)
   at System.Web.UI.BaseTemplateParser.GetUserControlType(VirtualPath virtualPath)
   at System.Web.UI.MainTagNameToTypeMapper.ProcessUserControlRegistration(UserControlRegisterEntry ucRegisterEntry)
   at System.Web.UI.BaseTemplateParser.ProcessDirective(String directiveName, IDictionary directive)
   at System.Web.UI.TemplateControlParser.ProcessDirective(String directiveName, IDictionary directive)
   at System.Web.UI.PageParser.ProcessDirective(String directiveName, IDictionary directive)
   at System.Web.UI.TemplateParser.ParseStringInternal(String text, Encoding fileEncoding)
   at System.Web.UI.TemplateParser.ProcessException(Exception ex)
   at System.Web.UI.TemplateParser.ParseStringInternal(String text, Encoding fileEncoding)
   at System.Web.UI.TemplateParser.ParseString(String text, VirtualPath virtualPath, Encoding fileEncoding)
   at System.Web.UI.TemplateParser.ParseFile(String physicalPath, VirtualPath virtualPath)
   at System.Web.UI.TemplateParser.ParseInternal()
   at System.Web.UI.TemplateParser.Parse()
   at System.Web.Compilation.BaseTemplateBuildProvider.get_CodeCompilerType()
   at System.Web.Compilation.BuildProvider.GetCompilerTypeFromBuildProvider(BuildProvider buildProvider)
   at System.Web.Compilation.BuildProvidersCompiler.ProcessBuildProviders()
   at System.Web.Compilation.BuildProvidersCompiler.PerformBuild()
   at System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath)
   at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
   at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
   at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound)
   at System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp)
   at System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath)
   at System.Web.UI.PageHandlerFactory.GetHandler(HttpContext context, String requestType, String virtualPath, String path)
   at System.Web.HttpApplication.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

1 个答案:

答案 0 :(得分:1)

由于您正在进行分组,因此在最终选择中需要

select new
{
                 art_id = (int?)g.key.art_id,
                 g.key.art_title,
                 g.key.art_permalink,

                 ... 
}

此外,但与您看到的错误无关,在您发布的SQL版本中,您正在进行内部联接,但在LINQ版本中,您正在执行左外部联接;你应该删除DefaultIfEmpty行。

编辑:由于你现在遇到最后的选择部分有问题,这里是后一个错误的答案(请注意'group sp by ...'成为新组{sp,p} by ...' -

 var q = (from sp in db.vArtParts
 where sp.sp_id == dd_type.SelectedValue.ToInt()
 join a in db.vArticles on sp.art_id equals a.art_id
 join p in db.vPrices on a.art_id equals p.art_id
 where a.art_visible == true && a.lng_id == 1
 group new {sp, p} by new {a.art_id, a.art_title, a.art_permalink} into g
 select new
     {
         art_id = (int?)g.Key.art_id,
         g.Key.art_title,
         g.Key.art_permalink,
         sp_code = g.Max(gg=>gg.sp.sp_code),
         pr_cat_name = g.Max(gg=>gg.p.pr_cat_name),
         pr_value = g.Max(gg=>gg.p.pr_value),
         pr_cat_id = (int?)g.Max(gg=>gg.p.pr_cat_id)
     }).ToList();