This is a migrated thread and some comments may be shown as answers.

Type Converters

2 Answers 101 Views
Development (API, general questions)
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Mensur
Top achievements
Rank 1
Mensur asked on 25 Oct 2011, 03:13 AM
I am trying to get a type converter to work but the app is complaining that the converter cannot be found. I created a FluentAPI project and added a converter there by following this FluentAPI blog post and this type converters Blog post. I basically have two classes: Book and Identifier and if I don't have a type converter everything seems to be fine. I am trying to convert date/time to a text representation which is how the date/time is stored in SQLite database:
public class SqliteDateToDateTime : AdoTypeConverter
{
    private bool nullable;
 
    public override AdoTypeConverter Initialize(IDataColumn user, Type clr,
                                                     IAdoTypeConverterRegistry registry, bool secondaryTable)
    {
        //first we need to ensure that the clr type can be handled by this converter
        if (clr == typeof (DateTime) && user.ResolvedSqlType == "varchar")
        {
            //then we need to set a flag to determine if the type is nullable
            nullable = typeof (DateTime?) == clr;
 
            //finally return base.Initialize, which ultimatly returns "this"
            return base.Initialize(user, clr, registry, secondaryTable);
        }
 
        //if the converter can not work with the specified clr type we return null
        return null;
    }
 
    public override object Read(ref DataHolder holder)
    {
        //check if the value is dbnull
        bool isNull = holder.Reader.IsDBNull(holder.Position);
 
        //set wheather or not there is a value
        holder.NoValue = isNull;
 
        //if the value is null, then we need to return default values
        if (isNull)
        {
            //if the type is nullable, and the value is null, we simply return null
            if (nullable)
                holder.ObjectValue = null;
                //if the value is null, and we need to box it, we set the objectvalue to 0
            else if (holder.Box)
                holder.ObjectValue = 0;
            else
                //other wise the value is null, so we simply return the default int value
                holder.Int32Value = 0;
        }
        else
        {
            //the value is not null, so here we want to pull the value out, and convert it to a string
            DateTime dt;
            string s = holder.Reader.GetValue(holder.Position).ToString();
            int index = s.IndexOf("+");
            if (index >= 0)
            {
                dt = DateTime.Parse(s.Substring(0, s.IndexOf("+")));
            }
            else
            {
                dt = DateTime.Parse(s);
            }
 
            //if the value is nullabel, or needs to be boxed, we set the ObjectValue Property of the DataHolder
            if (nullable || holder.Box)
                holder.ObjectValue = dt;
            else
                //otherwise we can set the Int32Value property to the parseed int value
                holder.DateTimeValue = dt;
        }
 
        //now we return our value
        return holder.ObjectValue; // (holder.Box || nullable) ? holder.ObjectValue : null;
    }
 
    public override void Write(ref DataHolder holder)
    {
        //set the db type
        holder.Parameter.DbType = System.Data.DbType.String;
 
        //if there is no value we could specify what to set the db field to
        if (holder.NoValue)
        {
            //in this case we just want to set it to null
            holder.Parameter.Value = null;
        }
        else
        {
            //When there is a value we simply need to take our CLR int, and convert it to a string
            //and then set the parameter info
            string s = holder.DateTimeValue.ToString("yyyy-MM-dd HH:mm:ss+00:00");
            holder.Parameter.Size = s.Length;
            holder.Parameter.Value = s;
        }
    }
 
    public override bool CreateLiteralSql(ref DataHolder holder)
    {
        //If there is no value, then we just want to query against null.
        if (holder.NoValue)
        {
            holder.StringValue = "NULL";
 
            //returning false indicates that no quotes are required. We want NULL instead of 'NULL'
            return false;
        }
        else
        {
            //convert the int value into a string, since that is what we are storing it as in the db
            holder.StringValue = holder.DateTimeValue.ToString("yyyy-MM-dd HH:mm:ss+00:00");
 
            // return true indicates that quotes are needed around the value
            return true;
        }
    }
 
    public override Type DefaultType
    {
        get { return typeof (DateTime); }
    }
}

    
Again, the class is in the FluentAPI project and here is the PrepareMapping method:

protected override IList<MappingConfiguration> PrepareMapping()
{
    List<MappingConfiguration> configurations = new List<MappingConfiguration>();
 
    MappingConfiguration<Book> bookConfiguration = new MappingConfiguration<Book>();
    bookConfiguration.MapType(p => new
    {
        id = p.Id,
        title = p.Title
    }).ToTable("books");
    bookConfiguration.HasProperty(x => x.PublishedDate)
        .ToColumn("pubdate")
        .HasColumnType("text")
        .WithConverter<SqliteDateToDateTime>();
    bookConfiguration.HasProperty(p => p.Id).IsIdentity();
 
    MappingConfiguration<Identifier> identifierConfiguration = new MappingConfiguration<Identifier>();
    identifierConfiguration.MapType(p => new
    {
        id = p.Id,
        book = p.BookId,
        type = p.Type,
        val = p.Value
    }).ToTable("identifiers");
    identifierConfiguration.HasProperty(p => p.Id).IsIdentity();
 
    identifierConfiguration.HasAssociation(p => p.Book).WithOpposite(c => c.Identifiers).HasConstraint((p, c) => p.BookId == c.Id);
 
    configurations.Add(bookConfiguration);
    configurations.Add(identifierConfiguration);
    return configurations;
}


The error I am getting is this: Could not load type 'Data.SqliteDateToDateTime' from assembly 'Telerik.OpenAccess.Runtime, Version=2011.2.713.3, Culture=neutral, PublicKeyToken=7ce17eeaf1d59342'.":"Data.SqliteDateToDateTime"} System.Exception {System.TypeLoadException}.

Any help is appreciated.



2 Answers, 1 is accepted

Sort by
0
Mensur
Top achievements
Rank 1
answered on 27 Oct 2011, 01:51 AM
There must be someone who knows the answer to this?
0
Ady
Telerik team
answered on 28 Oct 2011, 12:45 PM
Hello Mensur,

 I was able to reproduce the exception and we will fix this error. You can use the other overload of 'WithConverter' that use a string. Please change the code to the following:
bookConfiguration.HasProperty(x => x.PublishedDate)
                .ToColumn("pubdate")
                .HasColumnType("text")
                .WithConverter(typeof(SqliteDateToDateTime).AssemblyQualifiedName);

Hope this helps.

Do get back in case you need further assistance.

Greetings,
Ady
the Telerik team

NEW and UPDATED OpenAccess ORM Resources. Check them out!

Tags
Development (API, general questions)
Asked by
Mensur
Top achievements
Rank 1
Answers by
Mensur
Top achievements
Rank 1
Ady
Telerik team
Share this question
or