Skip to content
This repository has been archived by the owner on Mar 17, 2020. It is now read-only.

Cached value sometimes invalid #52

Closed
punppis opened this issue Sep 12, 2019 · 4 comments
Closed

Cached value sometimes invalid #52

punppis opened this issue Sep 12, 2019 · 4 comments

Comments

@punppis
Copy link

punppis commented Sep 12, 2019

Sometimes when using cache with parameters returns incorrect data.

List<int> currencyIds = ...; // only a few ids
Listt<Currency> currencies = await database.Currencies.Where(c => currencyIds.Contains(c.Id)).Cacheable().ToListAsync();

Sometimes I get empty list and sometimes partial results (missing items in list). During the lifetime of the app this data is never changed and definitely is available in the database. If error occurs, it fixes itself when updating the data from database next time even though the data has not changed!

If I remove Cacheable() the code works. If I remove the Where-clause (just cache all items) the code works.

This code is run with different currencyIds so I suspect some kind of cache collision; for conditions X you get data for conditions Y.

Dependencies:

<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.6"/>
<PackageReference Include="EFSecondLevelCache.Core" Version="2.6.2"/>
<PackageReference Include="CacheManager.Core" Version="1.2.0"/>
<PackageReference Include="CacheManager.Microsoft.Extensions.Caching.Memory" Version="1.2.0"/>
<PackageReference Include="CacheManager.Serialization.Json" Version="1.2.0"/>

Edit: tested also with 2.6.3 and problem persists

It seems to be an issue with having List<T>.Contains(...) inside Where-clause. This is only case where I have had problems. Seems like Contains does not leverage parameterization. Maybe its related to this?

@punppis
Copy link
Author

punppis commented Sep 13, 2019

After further investigation it seems like first cached result is always returned in this case.

Here is a test code with 100% reproduction:

async Task TestFunc(List<int> ids)
{
    List<Currency> currencies = await database.Currencies.Where(c => ids.Contains(c.Id)).OrderBy(c => c.Id).Cacheable().ToListAsync();
    string correct = ids.Join(); // joins values with , delimiter
    string result = currencies.Select(c => c.Id).Join();
    Debug.Log("Should be: " + correct);
    if(correct != result)
    {
        Debug.LogError("Invalid: " + result);
    }
    else
    {
        Debug.Log("ok");
    }
}

Tested like

await TestFunc(new List<int>() { 1, 2 });
await TestFunc(new List<int>() { 3 });
await TestFunc(new List<int>() { 1, 6, 8 });
await TestFunc(new List<int>() { 1, 2, 3, 6, 8 });
await TestFunc(new List<int>() { 1, 2 });

Results

[13.9.2019 8:09:47 INFO T:10] Should be: 1,2
[13.9.2019 8:09:47 INFO T:10] ok
[13.9.2019 8:09:47 INFO T:10] Should be: 3
[13.9.2019 8:09:47 ERROR T:10] Invalid: 1,2
[13.9.2019 8:09:47 INFO T:10] Should be: 1,6,8
[13.9.2019 8:09:47 ERROR T:10] Invalid: 1,2
[13.9.2019 8:09:47 INFO T:10] Should be: 1,2,3,6,8
[13.9.2019 8:09:47 ERROR T:10] Invalid: 1,2
[13.9.2019 8:09:47 INFO T:10] Should be: 1,2
[13.9.2019 8:09:47 INFO T:10] ok

As stated before, everything works as expected when removing Cacheable() from the query.

@VahidN
Copy link
Owner

VahidN commented Sep 15, 2019

Fixed it via #e088162

@VahidN VahidN closed this as completed Sep 16, 2019
@punppis
Copy link
Author

punppis commented Sep 16, 2019

Seems to be working, nice!

@lock
Copy link

lock bot commented Dec 15, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related problems.

@lock lock bot locked as resolved and limited conversation to collaborators Dec 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants