如何将此 Linq SQL 编写为动态查询(使用字符串)?

发布于 2024-08-26 10:16:24 字数 2420 浏览 4 评论 0原文

根据需要跳至“具体问题”。一些背景:

场景:我有一组产品,带有填充有 DDL 的“向下钻取”过滤器(查询对象)。每个渐进式 DDL 选择都将进一步限制产品列表以及 DDL 的剩余选项。例如,从工具中选择锤子会将产品尺寸限制为仅显示锤子尺寸。

当前设置:我创建了一个查询对象,将其发送到存储库,并将每个选项提供给 SQL“表值函数”,其中 null 值表示“获取所有产品”。

我认为这是一个很好的努力,但远不能接受 DDD。我想避免在 SQL 中进行任何“编程”,希望通过存储库完成所有操作。对此主题的评论将不胜感激。

具体问题:

我如何将此查询重写为 动态查询?类似于 101 Linq Examples 的链接会很棒,但是动态查询范围。我真的想将引号“”中的字段传递给此方法,我想要一个选项列表以及有多少产品具有该选项。

from   p in db.Products
group  p by p.ProductSize into g
select new Category { 
       PropertyType = g.Key,
       Count = g.Count() }

每个 DDL 选项都有“选择 (21)”,其中 (21) 是具有该属性的产品数量。选择一个选项后,所有其他剩余的 DDL 将使用剩余选项和计数进行更新。

编辑:附加说明:

.OrderBy("it.City") // "it" refers to the entire record
.GroupBy("City", "new(City)") // This produces a unique list of City
.Select("it.Count()") //This gives a list of counts... getting closer
.Select("key") // Selects a list of unique City
.Select("new (key, count() as string)") // +1 to me LOL.  key is a row of group
.GroupBy("new (City, Manufacturer)", "City") // New = list of fields to group by
.GroupBy("City", "new (Manufacturer, Size)") // Second parameter is a projection

Product
.Where("ProductType == @0", "Maps")
.GroupBy("new(City)", "new ( null as string)")// Projection not available later?
.Select("new (key.City, it.count() as string)")// GroupBy new makes key an object

Product
.Where("ProductType == @0", "Maps")
.GroupBy("new(City)", "new ( null as string)")// Projection not available later?
.Select("new (key.City, it as object)")// the it object is the result of GroupBy

var a = Product
        .Where("ProductType == @0", "Maps")
        .GroupBy("@0", "it", "City") // This fails to group Product at all
        .Select("new ( Key, it as Product )"); // "it" is property cast though

到目前为止,我学到的是 LinqPad 非常棒,但仍在寻找答案。我想最终,像这样的完全随机的研究将会盛行。哈哈。

编辑:

Jon Skeet 有一个绝妙的想法:将我需要的内容转换为 IGrouping。感谢乔恩·斯基特!转换对象后,您可以枚举集合并将结果输入到单独的列表中。

Skip to the "specific question" as needed. Some background:

The scenario: I have a set of products with a "drill down" filter (Query Object) populated with DDLs. Each progressive DDL selection will further limit the product list as well as what options are left for the DDLs. For example, selecting a hammer out of tools limits the Product Sizes to only show hammer sizes.

Current setup: I created a query object, sent it to a repository, and fed each option to a SQL "table valued function" where null values represent "get all products".

I consider this a good effort, but far from DDD acceptable. I want to avoid any "programming" in SQL, hopefully doing everything with a repository. Comments on this topic would be appreciated.

Specific question:

How would I rewrite this query as a Dynamic Query? A link to something like 101 Linq Examples would be fantastic, but with a Dynamic Query scope. I really want to pass to this method the field in quotes "" for which I want a list of options and how many products have that option.

from   p in db.Products
group  p by p.ProductSize into g
select new Category { 
       PropertyType = g.Key,
       Count = g.Count() }

Each DDL option will have "The selection (21)" where the (21) is the quantity of products that have that attribute. Upon selecting an option, all other remaining DDLs will update with the remaining options and counts.

Edit: Additional notes:

.OrderBy("it.City") // "it" refers to the entire record
.GroupBy("City", "new(City)") // This produces a unique list of City
.Select("it.Count()") //This gives a list of counts... getting closer
.Select("key") // Selects a list of unique City
.Select("new (key, count() as string)") // +1 to me LOL.  key is a row of group
.GroupBy("new (City, Manufacturer)", "City") // New = list of fields to group by
.GroupBy("City", "new (Manufacturer, Size)") // Second parameter is a projection

Product
.Where("ProductType == @0", "Maps")
.GroupBy("new(City)", "new ( null as string)")// Projection not available later?
.Select("new (key.City, it.count() as string)")// GroupBy new makes key an object

Product
.Where("ProductType == @0", "Maps")
.GroupBy("new(City)", "new ( null as string)")// Projection not available later?
.Select("new (key.City, it as object)")// the it object is the result of GroupBy

var a = Product
        .Where("ProductType == @0", "Maps")
        .GroupBy("@0", "it", "City") // This fails to group Product at all
        .Select("new ( Key, it as Product )"); // "it" is property cast though

What I have learned so far is LinqPad is fantastic, but still looking for an answer. Eventually, completely random research like this will prevail I guess. LOL.

Edit:

Jon Skeet had a fantastic idea: cast what I need as IGrouping<string, Product>. Thanks to Jon Skeet! Once you cast the object, you can enumerate over the sets and feed the results in to a separate List.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

安静被遗忘 2024-09-02 10:16:24

我不确定如何使用查询语法(如上所述)来执行此操作,但是使用方法语法,我们可以使用 Expression

using System;
using System.Linq;
using System.Linq.Expressions;

namespace LinqResearch
{
    public class Program
    {
        [STAThread]
        static void Main()
        {
            string columnToGroupBy = "Size";

            // generate the dynamic Expression<Func<Product, string>>
            ParameterExpression p = Expression.Parameter(typeof(Product), "p");

            var selector = Expression.Lambda<Func<Product, string>>(
                Expression.Property(p, columnToGroupBy),
                p
            );

            using (LinqDataContext dataContext = new LinqDataContext())
            {
                /* using "selector" caluclated above which is automatically 
                compiled when the query runs */
                var results = dataContext
                    .Products
                    .GroupBy(selector)
                    .Select((group) => new { 
                        Key = group.Key, 
                        Count = group.Count()
                    });

                foreach(var result in results)
                    Console.WriteLine("{0}: {1}", result.Key, result.Count);
            }

            Console.ReadKey();
        }
    }
}

I'm not sure how to do this using Query syntax (as above), but using Method syntax, we can use an Expression<Func< as shown below. This sample works against the AdventureWorks SQL Server database (Products table), and allows you to specify which column to group by using a string (in this sample I have chosen Size)

using System;
using System.Linq;
using System.Linq.Expressions;

namespace LinqResearch
{
    public class Program
    {
        [STAThread]
        static void Main()
        {
            string columnToGroupBy = "Size";

            // generate the dynamic Expression<Func<Product, string>>
            ParameterExpression p = Expression.Parameter(typeof(Product), "p");

            var selector = Expression.Lambda<Func<Product, string>>(
                Expression.Property(p, columnToGroupBy),
                p
            );

            using (LinqDataContext dataContext = new LinqDataContext())
            {
                /* using "selector" caluclated above which is automatically 
                compiled when the query runs */
                var results = dataContext
                    .Products
                    .GroupBy(selector)
                    .Select((group) => new { 
                        Key = group.Key, 
                        Count = group.Count()
                    });

                foreach(var result in results)
                    Console.WriteLine("{0}: {1}", result.Key, result.Count);
            }

            Console.ReadKey();
        }
    }
}
撧情箌佬 2024-09-02 10:16:24

如果您查看 C# 位 ,作者讨论了如何使用动态数据创建级联过滤器。听起来不像您正在使用动态数据,但他确实有一个很好的表达式生成器,可能对您有帮助。请参阅 BuildQueryBody,然后是 Iqueryable 上的扩展方法的以下部分。

由于您没有使用动态数据,因此您将需要处理无法访问“MetaForeignKeyColumn”对象的问题,但我怀疑他的方法可能会帮助您解决问题。

我希望这有帮助。

If you take a look at C# Bits, the author discusses how to create cascading filters using Dynamic Data. It does not sound like you are using Dynamic Data, but he does have a nice expression builder that might be helpful to you. See BuildQueryBody, and then the following section of extension methods on Iqueryable.

Since you are not using Dynamic Data, you will need to deal with not having access to a "MetaForeignKeyColumn" object, but I suspect his approach might help you with your question.

I hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文