我有一个包含很多列的表,并希望将所有字符串字段连续放在一起,这样我就可以通过它进行搜索,而无需依次将搜索字符串与每个字段进行比较。
如何在不明确说明每个列名的情况下迭代行?
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 ?
答案 0 :(得分:1)
如果您将每行作为列值的数组,则可以使用Aggregate。这是DataTable
的情况。
答案 1 :(得分:1)
试试这个:
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();
}
答案 2 :(得分:1)
您可以通过构建表达式树来编写这样的方法,如下所示:
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使用字段表示列;您可以将其更改为Visual Studio中生成的DataContexts的GetProperties)。
我们需要创建一个表达式,将这些字段提供给string.Concat语句。当后者接受一个字符串数组时,我们创建一个NewArrayInit表达式来构建数组。
接下来,我们调用Concat方法将字符串连接在一起,最后调用string.Contains方法来测试字符串文字是否在我们构建的表达式中。
以下是该方法在AdventureWorks上的运行方式:
void Main()
{
Addresses.Where (AnyColumnContains<Address> ("Seattle")).Dump();
}
Lambda翻译:
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