数据表——如何实现数据列表达式(计算列)的持久性



我有这个DataTable

FName LName Tag1 Tag2 Tag3 ... (not fixed, can be as many)

我想要的是

FName LName TagAll

因此,我创建了一个类型为string的列TagAll,表达式为
var expression = string.Empty;
// ... other code
// In a loop for all tag columns
expression = expression + " + ',' + " + tagColumn;
// at the end of loop
 dtContact.Columns["Tag_All"].Expression = expression;

如果我有3列,表达式是这样的

"Tag1 + ',' + Tag2 + ',' + Tag3"

例如数据为

FName LName    Tag1    Tag2    Tag3
Jeff  Atwood   test    tag     other
Matt  breeden  myTag   total   last

结果DataTable变成如下所示

FName LName    Tag1    Tag2    Tag3   Tag_All
Jeff  Atwood   test    tag     other  test, tag, other 
Matt  breeden  myTag   total   last   myTag, total, last

它很好,直到现在,但现在我想删除所有这些其他Tag(s)列。我试着做

dtContact.Columns.RemoveAt(2)但是会抛出'System.ArgumentException'

我猜这是因为该列在计算列表达式中使用,是正确的吗?因为当我移除第0列或第1列。它工作得很好。那么,有没有一种方法,我可以删除所有这些其他Tag(s)列,给他们在计算列表达式中使用?也许能让这个专栏持久存在?虽然我在谷歌上搜索了一下,但没有找到任何东西。

此外,就像我说的,这是不固定的,只有2,或3或n个这些Tag(s)列,它们是动态的,可以只有1,Tag1,最多任何…比如Tag88之类的

试试这个方法:

//Usage
DataTable dtMod = GetModifiedTable( dt);
//Function to return modified data table
public DataTable GetModifiedTable(DataTable dt)
{
    var columnList = dt.Columns.Cast<DataColumn>()
                                 .Where(x => x.ColumnName.StartsWith("Tag"))
                                 .Select(x => x.ColumnName)
                                 .ToArray();
    DataTable dtNew = new DataTable();
    dtNew.Columns.Add("FName");
    dtNew.Columns.Add("LName");
    dtNew.Columns.Add("Tag_All");
    var results  = dt.AsEnumerable().Select(r => 
                       dtNew.LoadDataRow( 
                         new object[] { 
                                r.Field<string>("FName"),
                                r.Field<string>("LName"),
                                GetTagValues(r, columnList)
                              }, false
                        ));
    dtNew.Rows.Add(results.ToArray());
    return dtNew;
}
//Function to return csv values of given column list
public string GetTagValues(DataRow r, string[] columns )
{
    string csv = string.Empty;
    foreach(string column in columns)
    {
        csv += r[column].ToString() + ",";
    }
    return csv.Substring(0, csv.Length - 1);
}

你不能这么做。你必须采取另一种方法。

添加TAG_ALL列,但不作为计算列。对于DataTable中的每一行,遍历所有TagX列并将它们相加,然后将值分配给Tag_All列。对每一行重复。完成后,现在可以删除TagX列。

根据行数的不同,这实际上可以非常快。

然而,我怀疑这是否是个好主意。如果要将DataTable绑定到某个网格,那么所需要做的就是不绑定TagX列,或者告诉grid使这些列不可见。

在处理数据表内的大量数据(大约500000行)时,遍历行需要花费时间(即使使用dt.AsEnumerable().Select()方法)。我正在寻找一个更快的方法,直到我发现以下解决方案:

  1. 将数据表(仅结构)克隆到新表
  2. 遍历列并删除表达式(设置为"),或者仅删除特定Datacolumn
  3. 的表达式
  4. 合并新数据表和旧数据表。

现在可以在不影响计算列的情况下删除原始列。

例子:

//assign expression
var expression = string.Empty;
expression = expression + " + ',' + " + tagColumn;
dtContact.Columns["Tag_All"].Expression = expression;
//Clone datatable structure
DataTable dtNew = dtContact.Clone();
//Remove expression from a specific column
dtNew.Columns["Tag_All"].Expression = "";
//Merge data with the new Table
dtNew.Merge(dtContact);
dtContact.Dispose();
//Now you can remove the column used within the expression
dtNew.Columns.RemoveAt(2);

查看下面的代码:

private void creatable()
{
   dt.Columns.Add("FName");
   dt.Columns.Add("LName");
   dt.Columns.Add("Tag1");
   dt.Columns.Add("Tag2");
   dt.Columns.Add("Tag3");
   dt.Columns.Add("Tag_All");
}
private void removeColumn()
{
        string temp = null;
        List<string> colToRemove = new List<string>();
        int colcount = dt.Columns.Count;
        for (int i = 0; i <colcount ;i++ )
        {
            temp = dt.Columns[i].ColumnName;
            if (temp == "Tag1" || temp == "Tag2" || temp == "Tag3")
            {
                colToRemove.Add(temp);
            }
            temp = null;
        }
        foreach (string item in colToRemove)
        {
            dt.Columns.Remove(item);
        }
    }

正在按你的要求工作

相关内容

  • 没有找到相关文章

最新更新