score:1

Accepted answer

You can write such a method by building an expression tree as follows:

Expression<Func<T, bool>> AnyColumnContains<T> (string value)
{
    var p = Expression.Parameter (typeof (T), "entity");

    var fieldAccessors = typeof (T)
        .GetFields()
        .Where (f => f.FieldType == typeof (string))
        .Select (f => Expression.Field (p, f))
        .ToArray();

    var fieldArray = Expression.NewArrayInit (typeof (string), fieldAccessors); 

    var concatCall = Expression.Call (typeof (string).GetMethod (
        "Concat", new[] { typeof (string[]) }), fieldArray);

    var contains = Expression.Call (
        concatCall, 
        typeof (string).GetMethod ("Contains", new[] { typeof (string) } ),
        Expression.Constant (value));

    return Expression.Lambda<Func<T, bool>> (contains, p);
}

First, we get all the fields from the entity type (LINQPad uses fields to represent columns; you can change this to GetProperties for DataContexts generated in Visual Studio).

We need to create an expression that feeds these fields into a string.Concat statement. As the latter accepts an array of strings, we create an NewArrayInit expression to build up the array.

Next, we call the Concat method to join the strings together, and finally, the string.Contains method to test whether the string literal is in the expression that we built.

Here's how the method runs on AdventureWorks:

void Main()
{
    Addresses.Where (AnyColumnContains<Address> ("Seattle")).Dump();
}

Lambda translation:

Addresses
   .Where (
      entity => 
         String
            .Concat (new String[] { entity.AddressLine1, entity.AddressLine2,
                                    entity.City, entity.PostalCode } )
            .Contains ("Seattle")
   )

SQL translation:

-- Region Parameters
DECLARE @p0 NVarChar(1000) = '%Seattle%'
-- EndRegion
SELECT [t0].[AddressID], [t0].[AddressLine1], [t0].[AddressLine2], [t0].[City],
       [t0].[StateProvinceID], [t0].[PostalCode], [t0].[rowguid] AS [Rowguid],
       [t0].[ModifiedDate]
FROM [Person].[Address] AS [t0]
WHERE ((([t0].[AddressLine1] + [t0].[AddressLine2]) + [t0].[City]) + [t0].[PostalCode])
      LIKE @p0

score:1

You can use Aggregate, if you have each row as an array of the values of the columns. This is the case with DataTable.

score:1

Try this:

    private void Form1_Load(object sender, EventArgs e)
    {
        DataTable dt = new DataTable();
        dt.Columns.Add(new DataColumn { DataType = typeof(int), ColumnName = "A" });
        dt.Columns.Add(new DataColumn { DataType = typeof(int), ColumnName = "b" });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "c" });
        DataRow r;
        for (int i=0;i<=5 ;i++)
        {
            r = dt.NewRow();
            r["A"] = i;
            r["b"] = i + 2;
            r["c"] = i.ToString();
            dt.Rows.Add(r);

        }
        var query = from DataRow row in dt.Rows.Cast<DataRow>().ToList()
                    let textUnion = GetFields(row)
                    select new { textUnion };
        dataGridView1.DataSource = query.ToList();

    }
    string GetFields(DataRow row)
    {
        StringBuilder retValue=new StringBuilder();

        for (int i = 0; i < row.ItemArray.Length;i++ )
        {
            retValue.Append(Convert.ToString(row[i]));
        }

        return retValue.ToString();
    }

Related Articles