名单(对T).RemoveAll也在不断变化previously缓存数据,它不应该是能够改变。我是疯了吗?我是、也在、它不、缓存

2023-09-07 09:27:28 作者:回头太难@

这已经让我疯狂了一整天,我觉得我有问题的范围缩小,但它只是没有任何意义怎么可能会发生。

This has been driving me insane all day and I think I have the problem narrowed down, but it just doesn't make sense how it could be happening.

我有2个公共共享功能和2个私人共享功能。一个提供定制对象的列表和一个过滤器的基础上,在函数调用的某些参数的对象。都返回列表(自定义对象)。 2.私人共享功能在列表中使用(T)的.RemoveAll功能。

I have 2 public shared functions and 2 private shared functions. One provides a list of custom objects and one filters the objects based on some parameters in the function call. Both return List(of custom object). The 2 private shared functions are the predicate functions used in the List(of t).RemoveAll function.

下面是简化的功能:

Public Shared Function NarrowItemList(ByVal OnSaleOnly As Boolean, ByVal InStockOnly As Boolean) As ItemList
    Dim iList As New ItemList

    iList = GetItemList()

    If OnSaleOnly Then
        iList.Items.RemoveAll(AddressOf GetOnSaleOnly)
    End If

    If InStockOnly Then
        iList.Items.RemoveAll(AddressOf GetInStockOnly)
    End If

    Return iList
End Function

Public Shared Function GetItemList() as ItemList
    Dim l As New ItemList

    If Not Cache("SpecialItemList") Is Nothing Then
        l = DirectCast(Cache("SpecialItemList"), ItemList)
    Else
        Using (Connection)
            //Get list here using datareader
        End Using

        Cache.Insert("SpecialItemList", l, Nothing, DateTime.Now.AddMinutes(30), System.Web.Caching.Cache.NoSlidingExpiration)
    End If

    Return l
End Function

    Private Shared Function GetOnSaleOnly(ByVal baditem As Item.BasicItemInfo) As Boolean
        If baditem.OnSale = False Then Return True
    End Function

    Private Shared Function GetInStockOnly(ByVal baditem As Item.BasicItemInfo) As Boolean
        If baditem.Qty = 0 Then Return True
    End Function

该GetItemList函数只调用了NarrowItemList功能,也没有别的地方的方案。调用它的第一次之后,即GetItemList数据返回的应该的缓存30分钟。

我已经调试这两个函数一行行。当GetItemList被称为第一次返回项目的正确#,比方说100一总数100项的对象,然后被传递给NarrowItemList功能的这份名单。根据我的想法,那GetItemList返回的数据应该是一个总的100个对象,为接下来的30分钟。

I have debugged both functions line by line. When the GetItemList is called the first time it returns the correct # of Items, let's say a total count of 100. That list of 100 item objects then gets passed to the NarrowItemList function. Based on my thinking, the data that GetItemList returns should be a total of 100 objects for the next 30 minutes.

在此处,混乱开始进来,如果我所说的NarrowItemList功能,并指定任一参数为真,它然后使用.RemoveAll功能和相关的predicate功能,以缩小列表。这就缩小了名单,理所应当,一个较低的数字,说,然后从那个函数返回的50项物品。所有好为止。

Here's where the confusion starts to come in. If I call the NarrowItemList function and specify either of the parameters as True, it then uses the .RemoveAll function and the associated predicate function to narrow the list. This then narrows the list, as it should, to a lower number, say 50 item objects that then get returned from that function. All good so far.

这里是我觉得我快要疯了。

现在,下一次我称之为GetItemList功能它只返回50项的对象,而不是100项的对象,它应该由于被设置缓存返回!我已经在调试器和运行很多很多不同的测试,看看参数是什么组合可能会造成问题验证了这一点。在我的测试,尽快的.RemoveAll功能之一是使用GetItemList项目列表将设置对什么NarrowItemList函数返回。

Now, the next time I call the GetItemList function it only returns 50 item objects, not the 100 item objects that it should be returning due to the cache being set! I have verified this in the debugger and by running many, many different tests to see what combinations of parameters may be causing the problem. In my testing, as soon as one of the .RemoveAll functions is used the GetItemList item list will get set to whatever the NarrowItemList function returned.

即使缓存没有被正确设置,不应该只是获取数据,再从数据库中,并再次返回100个项目?我能缺少???

Even if the cache wasn't being set correctly, shouldn't it just get the data again from the database and return 100 items again? What could I be missing???

推荐答案

当你回到那就是制作一个副本的缓存,而不是列表中,您允许的事情修改副本在缓存中。

When you return the list that is in your cache instead of making a copy of it, you are allowing things to modify the copy in the cache.

当它调用removeall过它删除缓存中从列表中的物品。

When it calls RemoveAll it is removing those items from the list in the cache.

尝试是这样的:(输入到答案,没有测试编译)

Try something like this: (typed into answer, not tested to compile)

Public Shared Function NarrowItemList(ByVal OnSaleOnly As Boolean, ByVal InStockOnly As Boolean) As ItemList
    Dim iList As New ItemList
    Dim items2 as IEnumerable(Of Item.BasicItemInfo) = GetItemList().Items
    If OnSaleOnly Then items2 = items2.Where(Function(x) x.OnSale)
    If InStockOnly Then items2 = items2.Where(Function(x) x.InStock)
    iList.AddRange(items2)
    Return iList
End Function 

请注意,你必须做更多的工作,如果你的BasicItemInfo类的东西,并不是一成不变的......,可以说一些这方面的工作应该GetItemList做[返回一个只读的IEnumerable摆在首位]

Note that you'll have to do even more work if your BasicItemInfo class is something that is not immutable... and arguably some of this work should be done in GetItemList [return a read-only IEnumerable in the first place]