Search code examples
c#sqlentity-frameworkormtelerik

Dynamic typeConvertion Entity Framework ORM


Hello i'm working with legacy code that uses Telerik ORM. bases on MSsql database that was migrated from db2 on backend.

As I know DB2 does not provide a dedicated type for storing boolean values in tables. There are different workarounds for this problem. In my case was decided to use custom Sql type BITTYPE:char(1), which in fact keeps two diffrent char(1) values ( '1' (true)and'0' (false)). Telerik ORM uses custom AdoTypeConverter to convert this char(1) values to domain boolean properties.

public class BitTypeToBooleanConverter : TypeConverterBase
{
    public BitTypeToBooleanConverter()
    {
        this.ConverterType = typeof(bool);
        this.NullableConverterType = typeof(bool?);
    }

    public override object Read(ref DataHolder holder)
    {
        bool n = holder.Reader.IsDBNull(holder.Position);
        holder.NoValue = n;
        if (n)
        {
            if (nullable)
                holder.ObjectValue = null;
            else if (holder.Box)
                holder.ObjectValue = false;
            else
                holder.BooleanValue = false;
        }
        else
        {
            string s = holder.Reader.GetValue(holder.Position).ToString();
            bool outValue = false;
            if (!bool.TryParse(s,out outValue))
            {
                if (s.Equals("1"))
                {
                    outValue = true;
                }
            }
            if (nullable || holder.Box)
                holder.ObjectValue = outValue;
            else
                holder.BooleanValue = outValue;
        }
        return (holder.Box || nullable) ? holder.ObjectValue : null;
    }

    public override void Write(ref DataHolder holder)
    {
        holder.Parameter.DbType = System.Data.DbType.String;
        if (holder.NoValue)
        {
            holder.Parameter.Size = 1;
            holder.Parameter.Value = null;
        }
        else
        {
            string s = (holder.BooleanValue ? "1" : "0");
            holder.Parameter.Size = s.Length;
            holder.Parameter.Value = s;
        }
    }

    public override bool CreateLiteralSql(ref DataHolder holder)
    {
        if (holder.NoValue)
        {
            holder.StringValue = "NULL";
            return false;
        }
        else
        {
            holder.StringValue = (holder.BooleanValue ? "1" : "0");
            return true; // inidicating that ' are needed around, because it is a character column (VARCHAR)
        }
    }

Q: I can't change database, but I need somehow to teach Entity Framework ORM works with same scenario

P.s After i had read the article (

i tried workaround this issue with using convention, but it has not brought results.

  1. BITTYPE:char(1) - Error: could not be found in the SqlServer provider manifest
  2. Char - **Error:**Schema specified is not valid. Errors: (8,12) : error 2019: Member Mapping specified is not valid. ..

Code snippet:

     public class BitTypeCharConvention : Convention
        {
            private const string DataType = "BITTYPE:char(1)";

            public BitTypeCharConvention()
            {
                Properties<bool>().Configure(c => c.HasColumnType(DataType));
            }
        }

I also know that i can try to create another property that will convert the value of the string, but i would like more "reusable" variant


Solution

  • Conclution: Through, after the carried-out searches i actually haven't found appropriate solution for the solution of the forehead. So was decided to stay with default Entity Framework behavior at data access level ( not to do any transformations ) and do this work at next application levels through mapping (automapper) (ie entity to domain model)