Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Monday, November 22, 2021

A tiny and very handy CachedValue class

In server-side programming it happens very often that getting a value takes a lot of time, but the result can be stored for some time. A classical answer to this is of course caching. The class below allows to wrap this in a very simple model.

using System;

namespace IBSoft.Helpers
{
    public class CachedValue<T>
    {
        private T        value;
        private double   ttlInSeconds;
        private Func<T>  getValue;
        private DateTime expireAt = DateTime.MinValue;

        public CachedValue(int ttlInSeconds, Func<T> getValue)
        {
            this.ttlInSeconds = ttlInSeconds;
            this.getValue = getValue;
        }

        public T Value
        {
            get
            {
                if (DateTime.UtcNow > this.expireAt)
                {
                    T oldValue = this.value;

                    this.value = getValue();

                    var now = DateTime.UtcNow;
                    this.expireAt = now.AddSeconds(ttlInSeconds);

                    if (!this.value.Equals(oldValue))
                        this.LastValueUpdate = now;
                }

                return this.value;
            }
        }

        /// <summary>
        /// set when the value changes
        /// </summary>
        public DateTime LastValueUpdate { get; private set; }

        /// <summary>
        /// invalidates the value and causes reload on the next call
        /// </summary>
        public void Invalidate()
        {
            this.expireAt = DateTime.MinValue;
        }

        /// <summary>
        /// add implicit type conversion to T so that it's possible to use CacheValue<T> without the need to do cv.Value
        /// </summary>
        /// <param name="cv"></param>
        /// <returns></returns>
        public static implicit operator T(CachedValue<T> cv)
        {
            return cv.Value;
        }
    }
}

Wednesday, January 30, 2013

ORA-06502 with RAW OUT parameter called from ODP.NET

An interesting problem popped up today while calling a PL/SQL stored procedure from ODP.NET. It turns out that when you have an output RAW parameter you MUST provide some buffer space for it while adding this parameter, even though the parameter is OUTPUT only.

Here's a part of the definition of the stored procedure in Oracle:

PROCEDURE bla-bla(o_user_guid OUT RAW(16)) ...

Here's how it's called from C#:

using (OracleCommand cmd = con.CreateCommand())
{
     ...
     cmd.AddParameter(new OracleParameter("o_user_guid", 
                                                                   OracleDbType.Raw,  
                                                                   ParameterDirection.Output));
}

Strangely enough this code returns the following error:

ORA-06502: PL/SQL: numeric or value error: raw variable length too long

Adding the size of 16 to the creation of the parameter does not help.


What helps though is adding a dummy buffer while creation of the parameter as follows:

using (OracleCommand cmd = con.CreateCommand())
{
     ...
     byte[] userGuidPlaceholder = new byte[16];

     cmd.AddParameter(new OracleParameter("o_user_guid", 
                                                                  OracleDbType.Raw,  
                                                                  16, 
                                                                  userGuidPlaceholder, 
                                                                  ParameterDirection.Output);
}

Weird.