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.