score:2

Accepted answer

couldn't you just do something like this?

[httppost]
public list<testrecord> search(testrecord testrecord){

    list<testrecord> records = _db.testrecords
                 .where(tr => string.isnullorempty(testrecord.testtype) ? true : tr.testtype == testrecord.testtype)
                 .where(tr => string.isnullorempty(testrecord.part.name) ? true : tr.part.name == testrecord.part.name)
                 //etc...
                 .tolist();

    return records;
}

essentially only filter if the input is there for every field in 1 big query?

score:0

the query doesnt have to be one single chain, you can split it up and insert some if:

var query = _db.testrecords.asqueryable();
if (string.isnullorempty(testrecord.testtype))
{
    query = query.where(x => x.testtype == testrecord.testtype);
}
if (string.isnullorempty(testrecord.part.name))
{
    query = query.where(x => x.part.name == testrecord.part.name);
}

// or, you can use an intermediate variable before returning to debug
return query.tolist();

score:0

i usually use an extension method like this:

public static iqueryable<t> where<t>(this iqueryable<t> that, object notnull, expression<func<t, bool>> predicate)
{
    if (!string.isnullorwhitespace(notnull?.tostring()))
    {
        return that.where(predicate);
    }

    return that;
}

then you can compose your linq query like this:

return s.query()
    .where(onlystatus, p => p.status == onlystatus)
    .orderbydescending(p => p.createddate)
    .tolist();

score:0

if you have only one class that has this requirement with only a limited number of properties, say less than 20, i wouldn't bother creating a generic solution for this. code a where that checks all properties. this has the advantage that if in future someone changes or removes a property your compiler will complain.

a nice solution would be to give your class an extension function:

public static bool hasnullproperties(this myclass x)
{
    return x.name == null
        && x.location == null
        && x.ordersize == null
        ...;
}

public static ienumerable<myclass> wherehasnullproperties(this ienumerable<myclass> source)
{
    return source.where(item => item.hasnullproperties();
}

usage somewhere in a linq statement

var result = dbcontext.myitems.wherehasnullproperties()
    .groupby(...)
    .select(...);

if you want a full proof solution that works on several classes, consider designing an interface:

interface ihasnullproperties
{
    bool hasnullproperties {get;}
}

your linq function will be:

 public static ienumerable<tsource> wherehasnullproperties<tsource>(
      this ienumerable<tsource> source)
      where tsource : ihasnullproperties
{
    return source.where(item => item.hasnullproperties();
}

finally a relatively slow method would be to use reflection: for any class, get all its get-properties that are nullable and see if any of them has a null value:

static bool hasnullprperties<tsource>(this tsource source)
    where tsource : class
{
     // take the type of the source, and get all properties of this type
     var result = source.gettype().getproperties()

         // keep only the readable properties (so you can do getvalue)
         // and those properties that have a nullable type
         .where(property => property.canread 
             && nullable.getunderlyingtype(property.type) != null)

         // for every of this properties, ask the source object for the property value:
        .select(property => property.getvalue(source))

        // and keep only the properties that have a null value
        .where(value => value == null);

        // return true if source has any property with a null value
        // = if there is any value left in my sequence
        .any();
    return result;  
}

Related Query

More Query from same tag