动态where子句在MVC应用程序的连接查询中使用Linq to SQL

问题描述 投票:2回答:4

我正在寻找一种方法来查询目录中的产品,使用根据产品所属类别分配给产品的属性过滤器。所以我涉及以下实体:

产品-Id -CategoryId

类别[Id,Name,UrlName]

属性[Id,CategoryId,Name,UrlName]

PropertyValues [Id,PropertyId,Text,UrlText]

ProductPropertyValues [ProductId,PropertyValueId]

当我将产品添加到目录时,将根据类别添加多个ProductPropertyValues,我希望能够通过选择一个或多个属性的值来过滤类别中的所有产品。业务逻辑和SQL索引和约束确保所有UrlNames和文本对于值属性和类别都是唯一的。

解决方案将是基于MVC3 EF代码的第一个应用程序,路由设置如下:

/products/{categoryUrlName}/{*filters}

滤波器路由部分具有可变长度,因此可以应用多个滤波器。每个过滤器都包含属性的UrlName和由下划线分隔的值的UrlText。

网址可能如下/ products / websites / framework_mvc3 / language_csharp

我将通过阅读URL收集我将在列表中保存的所有过滤器。现在是时候实际获得基于多个属性的产品了,我一直在努力找到正确的策略。

也许有另一种方法来实现过滤器。所有较大的网上商店都使用依赖于类别的过滤器,我仍在寻找实现此类功能的持久性部分的最佳方法。如果选择了多个过滤器,则建议的解决方案会生成“或”结果集。我可以想象,将一个text属性添加到product表中,其中所有属性值都存储为连接字符串也可以。我不知道这会花费多少性能。在租用时,将不会有复杂的连接,无论如何,属性及其值将作为文本接收。

也许过滤机制可以很好地完成客户端。

c# linq-to-sql dynamic join where-clause
4个回答
0
投票

关于这一点的棘手部分是将整个列表作为过滤器发送到数据库中。您构建越来越多where子句的方法可以起作用:

productsInCategory = ProductRepository
  .Where(p => p.Category.Name == category); 

foreach (PropertyFilter pf in filterList) 
{
     PropertyFilter localVariableCopy = pf;
     productsInCategory = from product in productsInCategory
       where product.ProductProperties
         .Any(pp => pp.PropertyValueId == localVariableCopy.ValueId)
       select product; 
}

另一种方法是使用List.Contains方法发送整个列表

List<int> valueIds = filterList.Select(pf => pf.ValueId).ToList();

productsInCategory = ProductRepository
  .Where(p => p.Category.Name == category)
  .Where(p => p.ProductProperties
    .Any(pp => valueIds.Contains(pp.PropertyValueId)
  );

0
投票
IEnumerable<int> filters = filterList.Select(pf => pf.ValueId);

var products = from pp in ProductPropertyRepository
               where filters.Contains(pp.PropertyValueId) 
               && pp.Product.Category.Name == category
               select pp.Product;

请记住,当使用Contains时,过滤器将作为sproc参数传递,这意味着必须注意不要超过sproc参数限制。


0
投票

我提出了一个解决方案,即使我能理解......通过使用'Contains'方法,您可以根据需要链接尽可能多的WHERE。如果WHERE是一个空字符串,则忽略它(或者将其评估为全选)。这是我在LINQ中连接2个表的示例,应用多个where子句并填充要返回到视图的模型类。

public ActionResult Index()
{
    string AssetGroupCode = "";
    string StatusCode = "";
    string SearchString = "";

    var mdl = from a in _db.Assets
              join t in _db.Tags on a.ASSETID equals t.ASSETID
              where a.ASSETGROUPCODE.Contains(AssetGroupCode)
              && a.STATUSCODE.Contains(StatusCode)
              && (
              a.PO.Contains(SearchString)
              || a.MODEL.Contains(SearchString)
              || a.USERNAME.Contains(SearchString)
              || a.LOCATION.Contains(SearchString)
              || t.TAGNUMBER.Contains(SearchString)
              || t.SERIALNUMBER.Contains(SearchString)
              )
              select new AssetListView
              {
                  AssetId = a.ASSETID,
                  TagId = t.TAGID,
                  PO = a.PO,
                  Model = a.MODEL,
                  UserName = a.USERNAME,
                  Location = a.LOCATION,
                  Tag = t.TAGNUMBER,
                  SerialNum = t.SERIALNUMBER
              };


    return View(mdl);
}

0
投票

我知道这是一个古老的答案,但如果有人看到这个我已经建立了这个项目:

https://github.com/PoweredSoft/DynamicLinq

哪个也应该可以在nuget上下载:

https://www.nuget.org/packages/PoweredSoft.DynamicLinq

您可以使用它来遍历来自查询字符串的过滤器并执行某些操作

query = query.Query(q =>
{
    q.Compare("AuthorId", ConditionOperators.Equal, 1);
    q.And(sq =>
    {
        sq.Compare("Content", ConditionOperators.Equal, "World");
        sq.Or("Title", ConditionOperators.Contains, 3);
    });
});
© www.soinside.com 2019 - 2024. All rights reserved.