перебирать поля используя linq - PullRequest
2 голосов
/ 10 мая 2011

У меня есть таблица с большим количеством столбцов, и я хочу объединить все строковые поля в строке, чтобы я мог выполнить поиск по ней, не сравнивая строку поиска с каждым полем по очереди.

Как перебрать строку без явного указания имени каждого столбца?

ColumnA | ColumnB | ... | ColumnN
---------------------------------
   A    |    B    | ... |    N   

Я бы хотел получить результат AB ... N

Это то, что я имею до сих пор

string searchString = "text";
var searchCandidate = ATable.Where( ... condition ...); // IQueryable<ATable>
searchCandidate. // what goes here to loop through all fields ?

Ответы [ 3 ]

1 голос
/ 10 мая 2011

Попробуйте это:

    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();
    }
1 голос
/ 11 мая 2011

Вы можете написать такой метод, построив дерево выражений следующим образом:

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);
}

Во-первых, мы получаем все поля из типа сущности (LINQPad использует поля для представления столбцов; вы можете изменить это на GetProperties для DataContexts, сгенерированных в Visual Studio).

Нам нужно создать выражение, которое подает эти поля в оператор string.Concat. Поскольку последний принимает массив строк, мы создаем выражение NewArrayInit для построения массива.

Затем мы вызываем метод Concat для объединения строк и, наконец, метод string.Contains, чтобы проверить, присутствует ли строковый литерал в построенном нами выражении.

Вот как метод работает в AdventureWorks:

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

Лямбда-перевод:

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

перевод SQL:

-- 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
1 голос
/ 10 мая 2011

Вы можете использовать Aggregate , если каждая строка является массивом значений столбцов. Это в случае с DataTable.

...