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.
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
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)