Previously I've asked about inserting a column into a dataset. I now have a similar question...namely merging two or more columns into a single column.
以前我曾询问过如何在数据集中插入一列。我现在有一个类似的问题......即将两列或多列合并为一列。
Lets say I have the following data set:
假设我有以下数据集:
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable());
ds.Tables[0].Columns.Add("id", typeof(int));
ds.Tables[0].Columns.Add("firstname", typeof(string));
ds.Tables[0].Columns.Add("lastname", typeof(string));
I am needing to combine the "firstname" and "lastname" columns into a single column called "name".
我需要将“firstname”和“lastname”列合并到一个名为“name”的列中。
Would it be best for me to create a method that merges two columns together or a more general one that can be used to merge multiple columns together?
我最好创建一个将两列合并在一起的方法,还是可以用来将多列合并在一起的更通用的方法?
My idea is to create a generalized method sort of like the following:
我的想法是创建一个类似于以下的通用方法:
MergeColumns(string format, string mergedColumn, DataTable dt, params string[] columnsToMerge)
MergeColumns(字符串格式,字符串mergedColumn,DataTable dt,params string [] columnsToMerge)
The user supplies a format as follows: "{0} {1}"
用户提供如下格式:“{0} {1}”
mergedColumn is the name of the new column...but it must be able to be the same as one of the columns that will be merged cause in my real world case I'm merging "name" and "given_names" into "name"...but I still want to be able to use it if I ever needed to merge "street", "city", "state" "postcode" etc into a column called "address".
mergedColumn是新列的名称...但它必须能够与将要合并的列之一相同,因为在我的真实案例中我将“name”和“given_names”合并为“name” ...但是如果我需要将“街道”,“城市”,“州”,“邮政编码”等合并到名为“地址”的列中,我仍然希望能够使用它。
The way I am thinking this would be used is as follows:
我认为这将使用的方式如下:
MergeColumns("{0} {1}", "name", dataTable, "firstname", "lastname");
MergeColumns(“{0} {1}”,“name”,dataTable,“firstname”,“lastname”);
given the above dataset, I would expect the resultant data set to look as follows:
鉴于上述数据集,我希望结果数据集看起来如下:
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable());
ds.Tables[0].Columns.Add("id", typeof(int));
ds.Tables[0].Columns.Add("name", typeof(string));
Does this seem like a reasonable approach? Does a method like this already exist? I don't want to reinvent the wheel. Also, am I creating a method that does more than I actually need right now?
这看起来像是一种合理的方法吗?这样的方法是否已经存在?我不想重新发明*。另外,我现在创建的方法比我实际需要的更多吗?
8 个解决方案
#1
it seems to me that this should happen in the data layer and not the logic layer. presumably the dataset consumer knows what data it needs and could request it from the datastore explicitly, without having to manipulate datasets.
在我看来,这应该发生在数据层而不是逻辑层。可能数据集消费者知道它需要什么数据,并且可以明确地从数据存储区请求它,而不必操纵数据集。
in a database scenario, i'm essentially proponing a multiple stored procedure approach and the dataset consumer would retrieve the data from the appropriate one.
在数据库场景中,我实际上是在推销多存储过程方法,而数据集使用者将从适当的方法中检索数据。
#2
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable());
ds.Tables[0].Columns.Add("id", typeof(int));
ds.Tables[0].Columns.Add("firstname", typeof(string));
ds.Tables[0].Columns.Add("lastname", typeof(string));
ds.Tables[0].Rows.Add(1,"torvalds", "linus");
ds.Tables[0].Rows.Add(2,"lennon", "john");
ds.Tables[0].MergeColumns("name", "lastname", "firstname");
foreach (DataRow dr in ds.Tables[0].Rows)
MessageBox.Show(dr["name"].ToString());
}
}
public static class Helper
{
public static void MergeColumns(this DataTable t, string newColumn, params string[] columnsToMerge)
{
t.Columns.Add(newColumn, typeof(string));
var sb = new StringBuilder();
sb.Append("{0}, ");
for (int i = 1; i < columnsToMerge.Length; ++i)
sb.Append("{" + i.ToString() + "}");
string format = sb.ToString();
foreach(DataRow r in t.Rows)
r[newColumn] = string.Format(format, columnsToMerge.Select(col => r[col]).ToArray() );
}
}
#3
If the dataset is specific enough, a MergeName() method is fine. This is especially true if you don't think you'll be using it in more than once place. A generic method will require considerably more work, but could be worth it if you're doing a lot of merging.
如果数据集足够具体,可以使用MergeName()方法。如果您认为自己不会在多个地方使用它,则尤其如此。通用方法需要更多的工作,但如果你做了很多合并,那么它是值得的。
Some things I can think of off the top of my head that you'll have to deal with:
我能想到的一些你必须要处理的事情:
- One issue you may run into is type checking; what happens if a user wants to merge a date field or a numeric field.
- What happens to the old fields? Will they remain or be deleted? If you're using this as a direct data source, you may want to remove left over columns, so some kind of
RemoveOldColumns
flag may be a good idea.
您可能遇到的一个问题是类型检查;如果用户想要合并日期字段或数字字段会发生什么。
旧油田会发生什么?它们会保留还是被删除?如果您将其用作直接数据源,则可能需要删除左侧列,因此某种类型的RemoveOldColumns标志可能是个好主意。
#4
alternatively, you can do this:
或者,您可以这样做:
public Form1()
{
InitializeComponent();
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable());
ds.Tables[0].Columns.Add("id", typeof(int));
ds.Tables[0].Columns.Add("firstname", typeof(string));
ds.Tables[0].Columns.Add("lastname", typeof(string));
ds.Tables[0].Rows.Add(1,"torvalds", "linus");
ds.Tables[0].Rows.Add(2,"lennon", "john");
ds.Tables[0].Columns.Add("name", typeof(string), "lastname + ', ' + firstname");
foreach (DataRow dr in ds.Tables[0].Rows)
MessageBox.Show(dr["name"].ToString());
}
#5
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable());
ds.Tables[0].Columns.Add("id", typeof(int));
ds.Tables[0].Columns.Add("firstname", typeof(string));
ds.Tables[0].Columns.Add("lastname", typeof(string));
ds.Tables[0].Rows.Add(1,"torvalds", "linus");
ds.Tables[0].Rows.Add(2,"lennon", "john");
ds.Tables[0].Columns.Add("name", typeof(string));
foreach (DataRow dr in ds.Tables[0].Rows) dr["name"] = dr["lastname"] + ", " + dr["firstname"];
foreach (DataRow dr in ds.Tables[0].Rows)
MessageBox.Show(dr["name"]);
#6
This Exactly was my requirement and after a lot of searching I ended up in deciding that its better to create your own datatable and use that as your datasource to the ListBox or DropDownList whichever is required.
这完全是我的要求,经过大量的搜索,我最终决定创建自己的数据表并将其用作ListBox或DropDownList的数据源,无论哪个都需要。
DataTable dt = new DataTable();
dt.Columns.Add("Test",typeof(String));
foreach (DataRow r in ds.Tables[0].Rows)
{
DataRow dr = dt.NewRow();
dr["Test"] = r["LastName"] + " ," + r["firstName"];
dt.Rows.Add(dr);
}
Here ds
is the dataset containing the main return table of the procedure.
这里ds是包含过程主返回表的数据集。
#7
string result = string.Join(",", dtTotalQuery.AsEnumerable().Select(row => dtTotalQuery.Rows[0].ItemArray[0] + " " + dtTotalQuery.Rows[0].ItemArray[1]));
#8
Extension Method With selectable seperator and position,
扩展方法可选择分离器和位置,
public static class Helper
{
public static void MergeColumns(this DataTable t, string newColumn, params string[] columnsToMerge)
{
t.Columns.Add(newColumn, typeof(string));
var sb = new StringBuilder();
sb.Append("{0}, ");
for (int i = 1; i < columnsToMerge.Length; ++i)
sb.Append("{" + i.ToString() + "}");
string format = sb.ToString();
foreach(DataRow r in t.Rows)
r[newColumn] = string.Format(format, columnsToMerge.Select(col => r[col]).ToArray() );
}
}
Usage
//DataTable dt
dt.MergeColumns("name", 0, " ", "lastname", "firstname");
#1
it seems to me that this should happen in the data layer and not the logic layer. presumably the dataset consumer knows what data it needs and could request it from the datastore explicitly, without having to manipulate datasets.
在我看来,这应该发生在数据层而不是逻辑层。可能数据集消费者知道它需要什么数据,并且可以明确地从数据存储区请求它,而不必操纵数据集。
in a database scenario, i'm essentially proponing a multiple stored procedure approach and the dataset consumer would retrieve the data from the appropriate one.
在数据库场景中,我实际上是在推销多存储过程方法,而数据集使用者将从适当的方法中检索数据。
#2
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable());
ds.Tables[0].Columns.Add("id", typeof(int));
ds.Tables[0].Columns.Add("firstname", typeof(string));
ds.Tables[0].Columns.Add("lastname", typeof(string));
ds.Tables[0].Rows.Add(1,"torvalds", "linus");
ds.Tables[0].Rows.Add(2,"lennon", "john");
ds.Tables[0].MergeColumns("name", "lastname", "firstname");
foreach (DataRow dr in ds.Tables[0].Rows)
MessageBox.Show(dr["name"].ToString());
}
}
public static class Helper
{
public static void MergeColumns(this DataTable t, string newColumn, params string[] columnsToMerge)
{
t.Columns.Add(newColumn, typeof(string));
var sb = new StringBuilder();
sb.Append("{0}, ");
for (int i = 1; i < columnsToMerge.Length; ++i)
sb.Append("{" + i.ToString() + "}");
string format = sb.ToString();
foreach(DataRow r in t.Rows)
r[newColumn] = string.Format(format, columnsToMerge.Select(col => r[col]).ToArray() );
}
}
#3
If the dataset is specific enough, a MergeName() method is fine. This is especially true if you don't think you'll be using it in more than once place. A generic method will require considerably more work, but could be worth it if you're doing a lot of merging.
如果数据集足够具体,可以使用MergeName()方法。如果您认为自己不会在多个地方使用它,则尤其如此。通用方法需要更多的工作,但如果你做了很多合并,那么它是值得的。
Some things I can think of off the top of my head that you'll have to deal with:
我能想到的一些你必须要处理的事情:
- One issue you may run into is type checking; what happens if a user wants to merge a date field or a numeric field.
- What happens to the old fields? Will they remain or be deleted? If you're using this as a direct data source, you may want to remove left over columns, so some kind of
RemoveOldColumns
flag may be a good idea.
您可能遇到的一个问题是类型检查;如果用户想要合并日期字段或数字字段会发生什么。
旧油田会发生什么?它们会保留还是被删除?如果您将其用作直接数据源,则可能需要删除左侧列,因此某种类型的RemoveOldColumns标志可能是个好主意。
#4
alternatively, you can do this:
或者,您可以这样做:
public Form1()
{
InitializeComponent();
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable());
ds.Tables[0].Columns.Add("id", typeof(int));
ds.Tables[0].Columns.Add("firstname", typeof(string));
ds.Tables[0].Columns.Add("lastname", typeof(string));
ds.Tables[0].Rows.Add(1,"torvalds", "linus");
ds.Tables[0].Rows.Add(2,"lennon", "john");
ds.Tables[0].Columns.Add("name", typeof(string), "lastname + ', ' + firstname");
foreach (DataRow dr in ds.Tables[0].Rows)
MessageBox.Show(dr["name"].ToString());
}
#5
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable());
ds.Tables[0].Columns.Add("id", typeof(int));
ds.Tables[0].Columns.Add("firstname", typeof(string));
ds.Tables[0].Columns.Add("lastname", typeof(string));
ds.Tables[0].Rows.Add(1,"torvalds", "linus");
ds.Tables[0].Rows.Add(2,"lennon", "john");
ds.Tables[0].Columns.Add("name", typeof(string));
foreach (DataRow dr in ds.Tables[0].Rows) dr["name"] = dr["lastname"] + ", " + dr["firstname"];
foreach (DataRow dr in ds.Tables[0].Rows)
MessageBox.Show(dr["name"]);
#6
This Exactly was my requirement and after a lot of searching I ended up in deciding that its better to create your own datatable and use that as your datasource to the ListBox or DropDownList whichever is required.
这完全是我的要求,经过大量的搜索,我最终决定创建自己的数据表并将其用作ListBox或DropDownList的数据源,无论哪个都需要。
DataTable dt = new DataTable();
dt.Columns.Add("Test",typeof(String));
foreach (DataRow r in ds.Tables[0].Rows)
{
DataRow dr = dt.NewRow();
dr["Test"] = r["LastName"] + " ," + r["firstName"];
dt.Rows.Add(dr);
}
Here ds
is the dataset containing the main return table of the procedure.
这里ds是包含过程主返回表的数据集。
#7
string result = string.Join(",", dtTotalQuery.AsEnumerable().Select(row => dtTotalQuery.Rows[0].ItemArray[0] + " " + dtTotalQuery.Rows[0].ItemArray[1]));
#8
Extension Method With selectable seperator and position,
扩展方法可选择分离器和位置,
public static class Helper
{
public static void MergeColumns(this DataTable t, string newColumn, params string[] columnsToMerge)
{
t.Columns.Add(newColumn, typeof(string));
var sb = new StringBuilder();
sb.Append("{0}, ");
for (int i = 1; i < columnsToMerge.Length; ++i)
sb.Append("{" + i.ToString() + "}");
string format = sb.ToString();
foreach(DataRow r in t.Rows)
r[newColumn] = string.Format(format, columnsToMerge.Select(col => r[col]).ToArray() );
}
}
Usage
//DataTable dt
dt.MergeColumns("name", 0, " ", "lastname", "firstname");