1

I am using Visual Studio, C# and SQLite for a Xamarin application and all is working well. However I am using a generic repository that I would like to extend to be able to add to the GET to add a check against 2 properties if the generic is of a specific type.

Here is the Generic respository pattern I am following

My GET as it sets right now looks like this:

public List<T> Get<TValue>(Expression<Func<T, bool>> predicate = null, Expression<Func<T, TValue>> orderBy = null)
{
    var query = db.Table<T>();

    if (predicate != null)
        query = query.Where(predicate);

    if (orderBy != null)
        query = query.OrderBy<TValue>(orderBy);

    return new List<T>(query);
}

However I would like to add something like this (pseudo code):

Where RecordOwner is the Type and RecordOwnerCompanyId and RecordOwnerUserId are the properties I would like to add to the predicate/where clause. Keep in mind that hte lambda does not work and that this is for SQLite(query is of type TableQuery<T>)

public List<T> Get<TValue>(Expression<Func<T, bool>> predicate = null, Expression<Func<T, TValue>> orderBy = null)
{
    var query = db.Table<T>();

    if (predicate != null)
        query = query.Where(predicate);

    if (orderBy != null)
        query = query.OrderBy<TValue>(orderBy);

    // Perform record owner checks
    if (typeof(RecordOwner).IsAssignableFrom(typeof(T)))
    {
        query = query.Where(x => RecordOwnerCompanyId == 1234 && x.RecordOwnerUserId == 1234);
    }

    return new List<T>(query);
}

Any help is greatly appreciated.

UPDATE:

I do have a working solution that will get my what I want however I would much prefer to solve this problem with the predicate , as with the way shown below it is using more memory with 2 lists. It has not been a negative impact on performance but is not the ideal solution I was looking for. If someone knows how I can do this all with the predicate that would be great.

New working example (not using predicate):

public List<T> Get<TValue>(Expression<Func<T, bool>> predicate = null, Expression<Func<T, TValue>> orderBy = null)
{
    var query = db.Table<T>();

    if (predicate != null)
        query = query.Where(predicate);

    if (orderBy != null)
        query = query.OrderBy<TValue>(orderBy);

    var memUser = JstMem.Default.User;

    // Perform record owner checks
    if (typeof(RecordOwner).IsAssignableFrom(typeof(T)))
    {
        return new List<T>(query).Where(x => (x as RecordOwner).RecordOwnerCompanyId == memUser.SelectedCompanyId && (x as RecordOwner).RecordOwnerUserId == memUser.UserId).ToList();
    }

    return new List<T>(query);
}
Community
  • 1
  • 1
Kyle
  • 1,013
  • 8
  • 16
  • Why not just use the existing predicate in the original Get method. `Get(x=>x.RecordOwnerCompanyId == 1234)` – Steve Davis Apr 06 '17 at 08:00
  • That is what I am doing currently but there are a lot of "GETS" and I am having issues with my team remembering to put them in all of them while they are coding. It would be much easier if the repository just handled it so that people can be competently ignorant of it. I did find a away to get it working but, it is not exact as I wanted because it is not adding onto the predicate but rather performing a little more work after, which will use a little more memory. I would rather do it with the predicate if possible. (See UPDATE above). – Kyle Apr 06 '17 at 15:26
  • Combining predicate expressions (to create a logical `AND` between them) isn't pretty, but it [can definitely be done](https://stackoverflow.com/a/457328/1644813). One trick to remember: you'll probably have to cast your `Expression>` to `object` before you can cast it to `Expression>` (the two predicates will need to have the same type in order to take advantage of the answer I linked above). – Kirill Shlenskiy Oct 12 '17 at 06:54

0 Answers0