【问题标题】:LINQtoSQL Retrieving a table according to the values of another table where it has a many to many relationship withLINQtoSQL 根据另一个表的值检索一个表,该表与该表具有多对多关系
【发布时间】:2009-05-04 18:43:47
【问题描述】:

我有以下三个表:

alt text http://img16.imageshack.us/img16/5499/linqtosqlquery.jpg

使用 LinqToSql,我想检索 InventoryItems 列表,其中 (pointsName="Level" AND pointsValue

请注意,maxStoreLevel 是一个整数,它是 pointsName = "Level" 的点行的值。

由于您不能在 Linq 中的另一个 where 中使用 where,我不知道如何检索提到的列表。

更新:这是根据要求提供的 UML 图

alt text http://img17.imageshack.us/img17/3403/umldiagram.jpg

为了进一步解释我的场景,这里是我表中的数据:

alt text http://img4.imageshack.us/img4/7847/linqexample.jpg

假设 maxStoreLevel 为 1,“Hanzo's Helmet”的 pointsValue = 1 其中 pointsName="Level" 并且还有一个名为“Buy Price”的点,因此应该返回它的行(与具有相同条件的任何其他 Inventoryitems 相同)

【问题讨论】:

  • 你定义了外键吗?能发个dbml图吗?
  • 我正在研究一个示例,但我需要对标准进行一些澄清...您说“其中 pointsName="Level", pointsName="Buy Price" 和 pointsValue = maxStoreLevel"。这是 (pointsName="Level" OR pointsName = "Buy Price") AND pointsValue = maxStoreLevel ... 还是 pointsName = "Level" OR (pointsName="Buy Price" AND pointsValue = maxStoreLevel)。此外,在 maxStoreLevel 上,是否只有一行 pointsName = "Level" 或者每个 InventoryItem 一行?我们可以假设每个 InventoryItem 都有一个具有该值的点吗?

标签: c# linq linq-to-sql


【解决方案1】:

好的,所以这不如 lambda 表达式漂亮,我仍然有点模糊 where 子句到底需要什么,因为 PointsName 不能同时是 Level 和 Buy Price,但我需要在某个地方开始对话。我猜您需要在积分表上进行 2 次连接,但由于您比我更了解您的设置,我猜您将能够接受并根据需要进行修改。让我知道我错过了什么......

var items = (From items in context.InventoryItems
             join itemPoints in context.InventoryItemPoints on items.InventoryItemID equals itemPoints.InventoryItemID
             join points in context.Points on itemPoints.pointsID equals points.pointsID
             where (points.pointsName == "Level" && itemPoints.pointsValue == maxStoreLevel) && points.pointsName == "Buy Price"
             select items).Distinct();

我知道原始文件不会返回行,因为点名称无法同时具有两个值,但根据您随后的更新,我认为您需要的是:

var items = (From items in context.InventoryItems
             join levelItemPoints in context.InventoryItemPoints on items.InventoryItemID equals levelItemPoints.InventoryItemID
             join levelPoints in context.Points on levelItemPoints.pointsID equals levelPoints.pointsID
             join priceItemPoints in context.InventoryItemPoints on items.InventoryItemID equals priceItemPoints.InventoryItemID
             join pricePoints in context.Points on priceItemPoints.pointsID equals pricePoints.pointsID
             where (levelPoints.pointsName == "Level" && levelItemPoints.pointsValue == maxStoreLevel) && pricePoints.pointsName == "Buy Price"
             select items).Distinct();

【讨论】:

  • 如您所说的那样工作,感谢您的帮助和耐心
【解决方案2】:

类似:

var items = inventoryItems.Where(
  invItem => invItem.InventoryItemPoints.Contains(
    iip => (iip.pointsName == "Buy Price" || iip.PointsName == "Level") &&
    iip.pointsValue == maxStoreLevel);

但根据您发布的内容,这有点猜测,如果不是这样,dbml 的屏幕截图会很有用;)

更新:好的 - 这显然是垃圾(抱歉,几杯酒太多了:)

试试这个:

var items = dataContext.inventoryItems.Where(
    invItem => ivnItem.InventoryItemPoints.Select(
        iip => iip.Point.PointName).Contains(
        "Buy Price")
        && invItem.InventoryItemPoints.Select(
            iip => iip.pointsValue).Contains(maxStoreLevel));

添加其他 pointNames 应该很容易...

【讨论】:

  • 说它不能将 lambda 表达式转换为 InventoryItemPoint 类型,因为它不是委托
  • 是的,这太垃圾了,我从来没有对 LINQ-To-SQL 的 SQL“IN”版本感到满意...
  • 这样尝试过: var InventoryItems = ydc.InventoryItems.Where ( invItem => invItem.InventoryItemPoints.Select( iip => iip.Point.pointsName).Contains("Buy Price") && ( invItem.InventoryItemPoints.Select(iip => iip.pointsValue).Contains((int)maxStoreLevel) && invItem.InventoryItemPoints.Select(iip => iip.Point.pointsName).Contains("Level")));但没有返回任何行:/
【解决方案3】:

虽然您不能将 where 子句加倍,但您可以使用子选择并使用 Count 来查看它们是否包含值。试试:

var items = from item in context.InventoryItems
    where (from iip in context.InventoryItemPoints
        join p in context.Points on p.pointsId equals iip.pointsId
        where iip.InventoryItemId == item.InventoryItemId 
                    && p.pointsName == "Level" && iip.pointsValue == maxStoreLevel
        select iip).Count() > 0
    && (from iip in context.InventoryItemPoints
        join p in context.Points on p.pointsId equals iip.pointsId
        where iip.InventoryItemId == item.InventoryItemId 
                    && p.pointsName == "Buy Price"
        select iip).Count() > 0
    select item;

【讨论】:

  • 它返回了 InventoryItems 表中的所有行。
  • 我认为这是一个不正确的结果?这是一个复杂的查询,但这个概念应该有效。我承认我可能不得不在调试器中稍微尝试一下才能完全解决它。
猜你喜欢
  • 2019-11-07
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-15
相关资源
最近更新 更多