我正在使用C#+ VS2008 + .Net + ASP.Net + IIS 7.0 + ADO.Net + SQL Server 2008.我有一个ADO.Net数据表对象,我想过滤掉重复/类似的记录(在我的判断记录是否重复/类似的特定规则 - 如果记录/行对于字符串列具有相同的值,我会将它们视为重复/类似记录),并且只保留其中一个重复/类似记录。
输出需要是数据表,如果可以在同一个数据表对象上操作过滤操作,则可以输出相同的数据表对象。
什么是最有效的解决方案?
答案 0 :(得分:2)
您使用的是.NET 3.5吗?如果转换数据行,则可以使用LINQ to Objects:
var distinctRows = table.Rows.Cast<DataRow>().Distinct(new E());
...
public class E : IEqualityComparer<DataRow>
{
bool IEqualityComparer<DataRow>.Equals(DataRow x, DataRow y)
{
return x["colA"] == y["colA"];
}
int IEqualityComparer<DataRow>.GetHashCode(DataRow obj)
{
return obj["colA"].GetHashCode();
}
}
或者更简单的方法,因为您将它基于单个列的值:
var distinct = from r in table.Rows.Cast<DataRow>()
group r by (string)r["colA"] into g
select g.First();
如果您需要从这些不同的行中创建一个新的DataTable,您可以这样做:
var t2 = new DataTable();
t2.Columns.AddRange(table.Columns.Cast<DataColumn>().ToArray());
foreach(var r in distinct)
{
t2.Rows.Add(r);
}
或者,如果使用业务对象会更方便,您可以轻松转换:
var persons = (from r in distinct
select new PersonInfo
{
EmpId = (string)r["colA"],
FirstName = (string)r["colB"],
LastName = (string)r["colC"],
}).ToList();
...
public class PersonInfo
{
public string EmpId {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
你可以在没有它的情况下完成LINQ to Objects所能做的一切:它只需要更多的代码。例如:
var table = new DataTable();
var rowSet = new HashSet<DataRow>(new E());
var newTable = new DataTable();
foreach(DataColumn column in table.Columns)
{
newTable.Columns.Add(column);
}
foreach(DataRow row in table.Rows)
{
if(!rowSet.Contains(row))
{
rowSet.Add(row);
newTable.Rows.Add(row);
}
}
您还可以使用类似的策略从原始表中删除重复的行,而不是创建新表。
答案 1 :(得分:1)
您可以使用select into
子句执行group by
,因此不会创建重复项。然后删除旧表并将您选择的表重命名为原始表名。
答案 2 :(得分:1)
我会在数据库层中执行此操作:
SELECT Distinct...
FROM MyTable
或者如果您需要聚合:
SELECT SUM(Field1), ID FROM MyTable
GROUP BY ID
将SELECT语句放在存储过程中。然后在.net中建立与数据库的连接,调用存储过程,执行.ExecuteNonQuery()。返回数据表中的行并将数据表返回给UI。