Accessing the ORM Mapping at runtime

2 posts, 0 answers
  1. Craig
    Craig avatar
    2 posts
    Member since:
    Oct 2011

    Posted 17 Jun 2013 Link to this post

    I previously have been using SqlCe 4.0 without any ORM for simple data management. The main table in my database contains approximately 500k rows, and I've found that updating it in bulk using SqlCeResultSet on a TableDirect SqlCeCommand is absolutely perfect.

    Up until now there have only been a few low-level requirements for the data once it is loaded, but I am now looking to do some more complicated UI and I believe this will be much more convenient using and ORM tool, and OA fit the bill nicely. I am now trying to simplify the SqlCeResultSet functionality by extending the context class. When reading from SqlCeResultSet, one accesses the fields as an indexed array. I am seeking to write a mapper between that and the properties of the class, but as I'm new to the architecture of your product, I'm struggling to get started with how columns map to properties (and how persistent types map to tables) at run time.

    So if my wrapper for a SqlCeResultSet is going to be a  "public class Table<T> { .... } " and assuming that I know the context, then I want to be able to say that T maps to table "X" in the database, (ie like context.GetAll<T>() might do) and also know which properties are mapped to which columns.

    Assuming for the moment that it is a straight 1-to-1 column to property, and there's no complex data type conversions going on, what would the rest of this method look like?

     

    OpenAccessContext context;

     

    private T Read(SqlCeResultSet resultset)
    {
        T result = Activator.CreateInstance<T>();

        // what goes here assuming that context above is set? what is the table name for T, 
        // what are the properties that are in play and which columns do they map to?

        
    return result;
    }

     

    EDIT:
     Some further way along. When my class accesses the result set, the following code gets executed:

     

    SqlCeResultSet resultSet;

    SqlCeResultSet ResultSet

    {

        get

        {

             if (resultSet == null)

            {

                resultSet = command.ExecuteResultSet(ResultSetOptions.Updatable | ResultSetOptions.Scrollable);

                 fieldNames = new string[resultSet.FieldCount];

                 setAccessors = new FastInvokeHandler[resultSet.FieldCount];

                 getAccessors = new FastInvokeHandler[resultSet.FieldCount];

           for (int i = 0; i < resultSet.FieldCount; i++)

                {

                    fieldNames[i] = resultSet.GetName(i);

                    getAccessors[i] = Invocation.GetMethodInvoker(typeof(T).GetProperty(fieldNames[i]).GetAccessors()[0]);

                    setAccessors[i] = Invocation.GetMethodInvoker(typeof(T).GetProperty(fieldNames[i]).GetAccessors()[1]);

                 }

            }
             return resultSet;

         }

    }

     

    and when I want to read from the result set, I call this:

     

     

     

    private T Read(SqlCeResultSet resultset)

    {

        T result = Activator.CreateInstance<T>();

       for (int i = 0; i < resultset.FieldCount; i++)

         {

            if (!resultset.IsDBNull(i))

                        setAccessors[i].Invoke(result, new object[] { resultset.GetValue(i) });

        }

        return result;
    }

    which is triggered by this (simplified to remove error checking etc)
     

    public T this[object[] key]

    {

        get 
        {

             if (ResultSet.Seek(DbSeekOptions.FirstEqual, key) && ResultSet.Read())

                 return Read(resultSet);

            else
                return default(T);
        }
    }

    This works extremely well, until I change the name of the field in OA. I have worked out how to get table names etc, but not the mapping between a property/field on the class and a column in the underlying table.

     

  2. Boris Georgiev
    Admin
    Boris Georgiev avatar
    190 posts

    Posted 20 Jun 2013 Link to this post

    Hello Craig,

    You can use the Telerik OpenAccess ORM Metadata Model which provides the entire mapping between the conceptual types and the relational types. For more information about the Metadata I suggest you to take a look at this documentation article.

    OpenAccess ORM
    provides MetadataContainer class as a runtime API that you can use to interact with the Metadata Model. In the MetadataContainer there is a List with PersistentTypes where you can find the mapping between the Classes and the Tables and between the Properties from a Class and the Column in a Table

    Also I would suggest you to take a look at the Code-Only Mapping(Fluent API) section in our online documentation. With a Fluent Mapping API you can define the data model using only code and you will have the complete control over the domain model mapping configuration and schema management.

    I hope that helps.

    Regards,
    Boris Georgiev
    Telerik
    OpenAccess ORM Q2 2013 brings you a more powerful code generation and a unique Bulk Operations support with LINQ syntax. Check out the list of new functionality and improvements shipped with this release.
  3. DevCraft banner
Back to Top