In Q1 2011, Telerik OpenAccess ORM introduced a flexible type conversion system. This type conversion system allows developers to instruct OpenAccess on how to map types that it may not support out of the box. This feature makes it possible for OpenAccess to work with built in UDTs, such as SQL Spatial and XML, as well as any custom UDTs developers create.
What is a User Defined Type?
SQL Server 2005 introduced user-defined types (UDTs). UDTs extend the SQL type system by allowing you to store objects and custom data structures in a SQL Server database. UDTs can contain multiple data types and can have behaviors, differentiating them from the traditional alias data types that consist of a single SQL Server system data type. UDTs are defined using any of the languages supported by the .NET common language runtime (CLR) that produce verifiable code. This includes Microsoft Visual C#® and Visual Basic® .NET. The data is exposed as fields and properties of a .NET class or structure, and behaviors are defined by methods of the class or structure. -Taken from MSDN
While this definition is based on MS SQL, most RDBMS have some support for UDTs: Oracle, Postgres, SQLAnywhere
What Exactly Can a Type Converter Do?
Lets say a class exposes a System.Drawing.Image property, out of the box OpenAccess would support persisting this as a byte array; but the backing field for the image property would need to be marked transient, and a private field to store the byte array would need to be added. In addition, there would be some wiring code in the model to convert the byte array back to an image.
The code for something like this would look similar to this:
A code like SetImage, and the back up byte property would need to exist for each Image property, and while this works perfectly, it is a prime example of where a type converter can be leveraged. Type converters enable fine grain control over how OpenAccess reads and writes fields to the DB. We will see how to accomplish this particular scenario using type converters in an upcoming blog. For now lets start with a basic type converter.
I want to keep the first example as simple as possible, so I will create a type converter that tells OpenAccess how to store a CLR Integer in a SQL varchar column.
A basic type converter skeleton, with comments for each method:
So lets start filling this out to create the varchar2IntConverter:
1. Create a new class inheriting from Telerik.OpenAccess.Data.AdoTypeConverter
2. Now wire up the DefaultType property, and return typeof(int).
3. Next up is the the Initialize method, OpenAccess will execute this method to find a suitable converter for a given CLR type. If the specified type can be handled by this converter we will return the converter, if the type can not be handled by the converter we will return null.
4. Now we will work through the Read method, this method is called when OpenAccess wants to read a field from the database.
5. The Write method tells OpenAccess how to convert the CLR type into what the database column is expecting, it is called when OpenAccess is writing a property to the database.
6. Last but not least, the CreateLiteralSql method must be wired up. OpenAccess will use this method to create the SQL it uses when a property with this type converter is queried.
At this point the new type converter is read to use! Take a look!
Wiring Up the Type Converter
Wiring up a type converter is very straight-forward when working with the Fluent Mapping API. When working with the visual designer, it takes a little extra work at the moment, but the team is working on making this much easier.
Wiring up a custom TypeConverter with the Fluent Mapping API
TypeConverters are set at the property level, as such when using the Fluent Mapping API developers simply need to use the .WithConverter<>() method when configuring property mappings:
Wiring up a custom TypeConverter with the Visual Designer
To set our custom converter in this case, we need to get the FullyQualifiedTypeName of the type converter. In this case it is: TypeConverters.Varchar2IntConverter, TypeConverters, Version=22.214.171.124, Culture=neutral, PublicKeyToken=null
1. Open the .Rlinq file, and expand the Model Schema Explorer
3. Navigate to the field in the table
where the converter will be used.
4. Select the property, and expand the properties window.
5. Find the Converter property, and paste in the fully qualified type name for the converter.
6. Save the changes, close the xml editor, and it is ready to use!
The application should now run as expected, and take advantage of the new TypeConverter.
If you get an error saying something like:
The metadata for field '_myIntStoredInString' of class 'VDWithTypeConverters.MyClass' cannot be initialized: Type converter initialization failed. The converter with name 'VariableLengthStringConverter' does not convert from CLR type 'System.Int32' to SQL type 'varchar'.
Parameter name: converterName
Actual value was OpenAccessRuntime.Data.VariableLengthStringConverter, Telerik.OpenAccess.Runtime, Version=2011.2.908.6, Culture=neutral, PublicKeyToken=7ce17eeaf1d59342.
This means, that the converter is not being picked up. Please ensure that the proper FullyQualifiedTypeName
is set if you are using the Visual Designer.
While this example may seem a bit contrived, the main goal here was to show the basics before diving into the more advanced things you can do with these new found powers. :)