Base solution for your next web application
Open Closed

Call application layer method within the PreInitialize() #1132


User avatar
0
sampath created

Hi,

I'm going to use Redis cache on my app.Other than the Redis cache,I would like to load my drop down related data (master data) within the application layer's method (MycompanyApplicationModule).Then users will not need to wait for the data base retrievals even for the first time.Hence I'm using Cache,it will not have 2nd time db call anyway. I think we can do it on the PreInitialize() method. So could you tell me how can I do that ? Is this the right approach ? Hope you'll give feedback.Thanks.

RedisConnectorHelper.cs

public class RedisConnectorHelper
    {
        private static readonly Lazy<ConnectionMultiplexer> LazyConnection =
            new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect("localhost"));

        public static ConnectionMultiplexer Connection => LazyConnection.Value;
    }

js

vm.getAllCities = function () {
                cityService.getAllCitiesAsync().success(function (result) {
                    vm.cities = result.items;
                    vm.toRefreshCitySearchableDropDown();
                    if (vm.cityId != 0) {
                        vm.getCityName(vm.cityId);
                    }
                });
            };

            vm.getAllCities();

Html

<div class="form-group">
                    <label class="control-label">@L("City")</label>
                    <select id="cityDropDown" required
                            class="form-control"
                            ng-options="a.id as a.name + ' | '+ a.zipCode for a in vm.cities"
                            ng-model="vm.property.address.cityId"
                            ui-jq="selectpicker"
                            ui-options='{ iconBase: "famfamfam-flag", tickIcon: "fa fa-check" }'
                            ng-change="vm.changedCity(vm.property.address.cityId)"
                            data-live-search="true" title="@L("PfSelectCity")">
                        <option value=""></option>
                    </select>
                </div>

CityAppService

public async Task<ListResultOutput<CityListDto>> GetAllCitiesAsync()
        {
            var cache = RedisConnectorHelper.Connection.GetDatabase();
            var values = JsonConvert.DeserializeObject<List<CityListDto>>(cache.StringGet(AppConsts.Cities));
            if (values != null) return new ListResultOutput<CityListDto>(values.OrderBy(o => o.Name).ToList());//from cache

            var cities = await _cityRepository.GetAllListAsync();
            cache.StringSet(AppConsts.Cities, JsonConvert.SerializeObject(cities.OrderBy(o => o.Name).MapTo<List<CityListDto>>()));//to cache
            return new ListResultOutput<CityListDto>(cities.OrderBy(o => o.Name).MapTo<List<CityListDto>>());
        }

3 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    You can not cache data in PreInitialize. You can do in PostInitialize, since you can not run query before initialize. I did not see caching in the code you shared?

  • User Avatar
    0
    sampath created

    Hi, Yes,I have updated the cache details.Please see that. Yes,I need to do it on the PostInitialize() method.Could you tell me how to do that ? The above mentioned cache details have been implemented on the Application layer.Thanks.

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Caching is generally done as lazy-load:

    • When you first time request it, it's got from database. For next requests, it's retrieved from cache.
    • If the cache is not used for a long time, it's automatically cleared. So, next request will again get from database.
    • If the data in cache changes somehow, you must drop the cache data because it's not valid.

    I strongly suggest this pattern, because this is nature of caching. Otherwise, you will have problems. In addition to that, you can request data from cache in PostInitialize method of your module. Thus, it's loaded once the application starts (and first user request directly get from cache).

    I will show you an example: I store tenant features on the cache and then not using db to check tenant features every time. How did I do it..

    1. Created a class to store data in the cache: <a class="postlink" href="https://github.com/aspnetboilerplate/module-zero/blob/master/src/Abp.Zero/MultiTenancy/TenantFeatureCacheItem.cs">https://github.com/aspnetboilerplate/mo ... cheItem.cs</a> Cache data class should not include entities (Since they are not well serializable).

    2. Getting data from cache or db: <a class="postlink" href="https://github.com/aspnetboilerplate/module-zero/blob/master/src/Abp.Zero/Application/Features/AbpFeatureValueStore.cs#L112">https://github.com/aspnetboilerplate/mo ... re.cs#L112</a>

    3. I created a class to remove an item from cache when it's changed: <a class="postlink" href="https://github.com/aspnetboilerplate/module-zero/blob/master/src/Abp.Zero/MultiTenancy/TenantFeatureCacheItemInvalidator.cs">https://github.com/aspnetboilerplate/mo ... lidator.cs</a>