HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Generic asynchronous SQLite search builder

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
genericsearchbuilderasynchronoussqlite

Problem

I am writing a database manager that reads and writes to a local SQLite database on a mobile device. It works pretty well for the most part, but read access is somewhat slow - it takes about 2-5 seconds to load 250 to 500 records. I've already gone and made some improvements where I can, but I'm hoping that there is more I can do.

I am using the Mono.Data.Sqlite API as my database driver.

The following methods are meant to be used with generics. This means I need to use reflection in order to populate model properties (or at least that's the only way I can think of - let me know if there are better ways).

The FindAsync method takes two arguments. The first is a string the represents the WHERE clause of a SQL query. This string can use a format similar to String.Format() to allow the user to specify custom parameters (instead of using {0} to mark a parameter, you would instead use @0). The second parameter is a list of objects that will be used as parameters in the WHERE clause. It returns a list of objects of type T for which the WHERE clause is true. For an example of how this method is called, please see the bottom of this question.

The type of T must be an IModel, which is an in-house interface that specifies objects that can be stored in the SQLite database. Though these objects do have a little bit of specialization, for the purposes of this review they are more or less just POCOs.

```
public async Task> FindAsync(string whereClause, params object[] parameters) where T : IModel
{
// This method will ensure the DB connection is valid (verifies DB exists, initializes Connection, etc...)
VerifyInitializationStatus();

IEnumerable retList;
using (var cmd = Connection.CreateCommand())
{
InitializeFindCommand(cmd, whereClause, parameters);
using (var reader = await Task.Run(() => cmd.ExecuteReader()))
retList = ParseSqliteReader(reader);
}
return retList;
}

private void InitializeFindComma

Solution

Reflection is slow. That line probably doesn't help your performance :

var model = (T)Activator.CreateInstance(typeof(T));


I notice that you always create your instance with parameterless constructors. So you could add the type constraint new() in your class. That means you could do :

var model = new T();


That'd be faster and well... clearer.

You also use reflection to get properties. But you do it every time you make a query. You should cache this, after all, there's not much chances an object will gain properties during runtime :p (By caching, I mean adding your properties once in a static dictionary, so you won't need to get them twice or more.)

Overall, you're using reflection to map properties to your object, and that is probably the cause of your problem. You should use another solution. For example, I recently wrote a question about a property mapper using compiled Linq expressions. That solution is much faster than using reflection (like, way faster) but someone wrote an answer that proposes another solution I didn't explore yet that is even faster to map properties.

Overall, your performance problem is very probably related to the use of reflection!

Code Snippets

var model = (T)Activator.CreateInstance(typeof(T));
var model = new T();

Context

StackExchange Code Review Q#113404, answer score: 10

Revisions (0)

No revisions yet.