【问题标题】:Trying to implement an SQL query in LINQ尝试在 LINQ 中实现 SQL 查询
【发布时间】:2014-01-22 10:09:41
【问题描述】:

我正在尝试在 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();

*更新:错误消息:

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

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)

【问题讨论】:

  • 编译时或运行时错误消息或只是不同的结果?如果可用,您可以尝试在 IQueryable 上调用 ToTraceString 来检查 LINQ 查询将生成的 SQL。
  • 错误信息不可用。但是查询工作没有分组,像这样(我更新了问题内容)
  • sp.sp_id = 31 是不必要的吗?你为什么不把它包括在你的 LINQ 中?发布错误消息,因为实际上,我们还要如何确定问题所在?此外,如果您的 LINQ 提供程序是 NHibernate,您现在应该放弃。 LINQ 不是很好。
  • sp.sp_id setted in where sp.sp_id == dd_type.SelectedValue.ToInt() 我在我的问题中添加了一条错误消息。
  • 你能说明你对查询的使用吗?

标签: c# sql linq


【解决方案1】:

既然是分组,在最后的选择中你需要

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

                 ... 
}

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

编辑:由于您现在在最后一个 Select 部分遇到问题,这是后一个错误的答案(请注意,'group sp by ...' 变为 group new {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();

【讨论】:

  • 我添加了这段代码并得到了错误'vArtPart' does not contain a definition for 'pr_cat_name' and no extension method 'pr_cat_name' accepting a first argument of type 'vArtPart' could be found 如何更改这些行? sp_code = g.Max(gg=&gt;gg.sp_code), pr_cat_name = g.Max(gg=&gt;gg.pr_cat_name), pr_value = g.Max(gg=&gt;gg.pr_value), pr_cat_id = (int?)g.Max(gg=&gt;gg.pr_cat_id)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多