passing params expression results in strange error
Asked Answered
S

2

4

I have a model call address, with that model i have created a few crud operations, in the process of doing this i want a way i could create a query based on any number of properties:

public static IEnumerable<address> GetByParams(Expression<Func<address, bool>> predicate, int? pageNumber, int? pageSize)
    {
        using (IDbConnection db = DbFactory.OpenDbConnection())
        {
            if ((pageNumber != null) && (pageSize != null))
            {
                var data = db.Where<address>(predicate).Skip((int) pageNumber).Take((int) pageSize).ToList();
                if (data.Any())
                {
                    data[0].TotalCount = data.Count();
                    data[0].TotalPages = (int) (data.Count()/pageSize);
                }
                return data;
            }
            //this is the code that creates the error
            return db.Where<address>(predicate);
        }
    }

I have then tried testing this code with:

ViewBag.PossibleBilling = new SelectList(address.GetByParams(x=> x.AddressType == 2,null,null),0);

However this results in the strangest error ever: (the error is not from the selectList )

The given key was not present in the dictionary.

I have tried to google this, but the results are more complicated to fish through than the actual error. I guess it has something to do with me not setting up predicate as the right type, or that something has to happen to predicate before i pass it into where.

Reason for the predicate is that i have a TT file that generates all this for me, so i dont know property names and needs to remain anom.

EDIT:

For clarity on future reading: I am using this against servicestack.ormlite: https://github.com/ServiceStack/ServiceStack.OrmLite

I am trying to create a TT file to build some basic crud methods with my model, I have found this piece of code within ormlite:

System.Collections.Generic.List<T> Where<T>(this System.Data.IDbConnection dbConn, object anonType) Member of ServiceStack.OrmLite.OrmLiteReadConnectionExtensions

Where object anonType eould be my own query / predicate

The paging code is wrong, however this is not the course of the error, The problem solved by drax is that I was using a Where, when all i needed was a select with params.

This improvement changes the usage of code to the following procedure:

public static List<T> Select<T>(this IDbConnection dbConn, Expression<Func<T, bool>> predicate)

This procedure accepts Expression and eliminates the error

thanks

Speechmaker answered 29/3, 2013 at 14:36 Comment(8)
where exactly is exception thrown?Mighell
You have to post the whole stack trace of the exception. Also you have a bug - data.Count() will always return the size of the current page, not the whole set.Extemporaneous
Why do you use Expression<Func<address, bool>> instead of a simple Func<address, bool> for the parameter type?Gillies
What is the content of the database table and what is the expected return of that statement? You need to eliminate possible sources of errors. You could try call that statement directly with x=> x.AddressType == 2 or test if it works without the where.Canales
@Canales The reason i have not listed the content here is because the address can be anything you like, its just an address, and expected type is at the top with IEnumerable<address> Also unable to call addressType == as this is a TT file with a generic query for any type that is unknown to the TT file, the question was more directed at the people who would understand the question please see comments from JOn and drax below for better understanding, but thanks for your inputSpeechmaker
@dirk Thanks for your comment, however the usage of Expression was not the course of this errorSpeechmaker
@Mighell The exception is listed in the initial Post and shows "The given key was not present in the dictionary.", I have listed this as Error, however this is also ExceptionSpeechmaker
@Knaģis Correct with the count(), thanks and you are correct and the final code will be improved once i have worked out my problems with the predicate, you are right that i should be counting the whole possible results, rather than the count of my paged results, and running this code would actually only result in a page size = 1Speechmaker
J
2

I think you should use Select instead of Where extension method. So your example could be written like:

public static IEnumerable<address> GetByParams(Expression<Func<address, bool>> predicate, int? pageNumber, int? pageSize)
{
    using (IDbConnection db = DbFactory.OpenDbConnection())
    {
        if ((pageNumber != null) && (pageSize != null))
        {
            var data = db.Select<address>(predicate).Skip((int) pageNumber).Take((int) pageSize).ToList();
            if (data.Any())
            {
                data[0].TotalCount = data.Count();
                data[0].TotalPages = (int) (data.Count()/pageSize);
            }
            return data;
        }
        //this is the code that creates the error
        return db.Select<address>(predicate);
    }
}
Judd answered 15/4, 2013 at 18:52 Comment(6)
No, that would project the addresses into booleans... which clearly isn't what's required, based on the signature of the method.Continuate
@Jon Skeet I think this should be correct. This extension comes from OrmLite and is described here Method signature looks like this: public static List<T> Select<T>(this IDbConnection dbConn, Expression<Func<T, bool>> predicate)Judd
Wow, how bizarre and completely against the rest of LINQ. (It fits in with DataTable.Select, admittedly, but ick ick ick.)Continuate
I cannot argue with that. It would be also quite slow, since it will take all items from database, before it does paging.Judd
Hi, sorry for delay have not had chance to check this as i have just returned from the dales, however I do realise that the code is Not good here with the paging, my main problem was with just passing the params over, thanks for the info on using select rather than WHERE, my head was so wrapped around using a where that i was totally blind sided by the the very thing itself. @Jon The bool thing threw me too and to be honest i don't really understand why this is a bool, but would appreciate any feedback on how i could improve this process and better tune my TT files.Speechmaker
@drax, check the answer here to avoid the performance hit:#18825221Senaidasenalda
D
1

My guess is that the address.GetByParams(...) part returns an empty set and therefore the default selection of the SelectList can't be set to the 0th element (it has none).

Check whether you actually get results from the database through your GetByParams. Do any addresses exist that have AddressType equal to 2?

Dithionite answered 29/3, 2013 at 14:44 Comment(6)
nope there are 2 addresses and they pull if i use Get(id) etc, just this oneSpeechmaker
also the error is not on the selectList, The error in question is with regards to the predicate, the select list is just an example of calling thats allSpeechmaker
Okay, maybe use something like db.Address.Where(predicate) or Db.Set<Address>.Where(predicate) instead of the current db.Where<address>(predicate)Dithionite
thats what i am using, this is servicestack there is no set<> but calling the .where() is the same. this would normally be .where(x => x.AddressTYpe == 2) but what i am trying to do is pass over (x => x.AddressType) as a param so that from the controllers i can add anything, and query on anything and i am sure that it is this method that causes the error, rather than the way its called. where takes in a type of Object anonTypeSpeechmaker
public static System.Collections.Generic.List<T> Where<T>(this System.Data.IDbConnection dbConn, object anonType) Member of ServiceStack.OrmLite.OrmLiteReadConnectionExtensionsSpeechmaker
@davethecoder: You should edit all of this information - and the exception stack trace - into the question.Continuate

© 2022 - 2024 — McMap. All rights reserved.