如何在循环中追加IQueryable

时间:2011-11-08 16:17:15

标签: c# entity-framework webforms

我有一个简单的foreach循环,它遍历我存储在用户购物篮中的productID,并从数据库中查找产品的详细信息。

从我的代码中可以看出,我目前所拥有的将返回屏幕上的最后一项 - 因为变量在循环中被覆盖。我希望能够将其连接起来,以便我只能在购物篮中显示商品的详细信息。

我知道我可以做一些非常简单的事情,比如只在我使用的转发器中存储ProductIDs,并且onitemdatabound在那里调用数据库但是我想在可能的情况下只进行一次数据库调用。

目前我有以下内容(从示例中删除了复杂的连接,但如果这很重要,请告诉我):

IQueryable productsInBasket = null;
    foreach (var thisproduct in store.BasketItems)
    {
        productsInBasket = (from p in db.Products
                                 where p.Active == true && p.ProductID == thisproduct.ProductID
                                 select new
                                 {
                                     p.ProductID,
                                     p.ProductName,
                                     p.BriefDescription,
                                     p.Details,
                                     p.ProductCode,
                                     p.Barcode,
                                     p.Price
                                 });
    }

    BasketItems.DataSource = productsInBasket;
    BasketItems.DataBind();

感谢您的帮助!

2 个答案:

答案 0 :(得分:7)

听起来你真的想要这样的东西:

var productIds = store.BasketItems.Select(x => x.ProductID).ToList();
var query = from p in db.Products
            where p.Active && productIds.Contains(p.ProductID)
            select new
            {
                p.ProductID,
                p.ProductName,
                p.BriefDescription,
                p.Details,
                p.ProductCode,
                p.Barcode,
                p.Price
            };

答案 1 :(得分:0)

在Jon的答案中,它的工作正常,但IQueryable将被转换为IEnumerable,因为你在它上面调用ToList()。这将导致执行查询并检索答案。对于您的情况,这可能没问题,因为您想要检索篮子的产品,以及产品数量可能相当小的地方。

然而,我面临着类似的情况,我想为会员检索朋友。友谊取决于两个成员属于哪个组 - 如果他们共享至少一个组,则他们是朋友。因此,我必须为特定成员检索所有组的所有成员资格,然后从这些组中检索所有成员。

ToList方法在我的情况下不适用,因为每当我想以各种方式处理我的朋友时,它将执行查询,例如找到我们可以分享的东西。从数据库中检索所有成员,而不是仅仅处理查询并在最后可能的时间执行它将会破坏性能。

但是,我在这种情况下的第一次尝试就是这样做 - 检索我所属的所有组(IQueryable),初始化List结果(IEnumerable),然后遍历所有组并将所有成员附加到结果中(如果它们是尚未列入清单。最后,由于我的界面强制要求返回IQueryable,我使用AsIQueryable返回了列表。

这是一段令人讨厌的代码,但至少它起作用了。它看起来像这样:

var result = new List<Member>();
foreach (var group in GetGroupsForMember(member))
    result.AddRange(group.GroupMembers.Where(x => x.MemberId != member.Id && !result.Contains(x.Member)).Select(groupMember => groupMember.Member));
return result.AsQueryable();

然而,这是不好的,因为我将所有共享成员添加到列表中,然后将列表转换为IQueryable以满足我的发布条件。每次我想用它们做什么的时候,我都会检索受数据库影响的所有成员。

想象一下分页列表 - 我只想从这个列表中选择一个范围。如果使用IQueryable完成此操作,则只需使用分页语句完成查询。如果使用IEnumerable完成此操作,则查询已执行,并且所有操作都将应用于内存中的结果。

(正如您可能还注意到的,我还向下导航实体的关系(GroupMember =&gt; Member),这会增加耦合可能会导致各种令人讨厌的情况。我也希望删除此行为。)

所以,今晚,我又进行了一轮,结果采用了更为简单的方法,我选择了这样的数据:

var groups = GetGroupsForMember(member);
var groupMembers = GetGroupMembersForGroups(groups);
var memberIds = groupMembers.Select(x => x.MemberId);
var members = memberService.GetMembers(memberIds);

两个Get方法遵循IQueryable并且永远不会将其转换为列表或任何其他IEnumerable。第三行只是在IEnumerable的ontop上执行LINQ查询。最后一行只获取成员ID并从另一个服务中检索所有成员,这也仅适用于IQueryables。

这在性能方面可能仍然很糟糕,但如果需要,我可以在以后进一步优化它。至少,我避免加载不必要的数据。

如果我在这里非常错误,请告诉我。

相关问题