2010-07-20 11 views
1

J'utilise C# + VS2008 + .Net + ASP.Net + IIS 7.0 + ADO.Net + SQL Server 2008. J'ai un objet datatable ADO.Net, et je veux filtrer les enregistrements dupliqués/similaires (dans mon spécifique règle pour juger si les enregistrements sont en double ou similaires - si enregistrement/ligne a la même valeur pour une colonne de chaîne, je les traiterai comme des enregistrements en double/similaires), et ne conserver qu'un de ces enregistrements en double/similaires.comment obtenir des enregistrements distincts dans datatable?

La sortie doit être datatable, peut sortir le même objet pouvant être daté si l'opération de filtrage peut être effectuée sur le même objet pouvant être daté.

Quelle est la solution la plus efficace?

+3

Est-ce que vous vous souciez de * qui * des similaires/duplicats que vous souhaitez conserver? Le "premier" (en stockage)? Une autre colonne discriminante? Voulez-vous effectuer un agrégat sur les autres valeurs de colonne? Plus de détails sont requis. –

+0

Gardez l'un d'entre eux est ok. Des bonnes idées? – George2

+2

Vous répertoriez la pile technologique complète, mais il semble que vous ne souhaitiez que récupérer des objets d'un objet DataTable. Est-ce correct? Avez-vous le contrôle sur l'origine de ces données? Si vous ne pouvez en premier lieu sélectionner que des éléments distincts de la base de données, cela sera plus efficace que de filtrer les éléments en double dans une base de données ultérieure. – StriplingWarrior

Répondre

2

Utilisez-vous .NET 3.5? Si vous lancez vos lignes de données, vous pouvez utiliser 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(); 
    } 
} 

Ou une encore plus simple façon, puisque vous basant sur les valeurs de colonne unique:

var distinct = from r in table.Rows.Cast<DataRow>() 
       group r by (string)r["colA"] into g 
       select g.First(); 

Si vous devez faire une nouvelle sur DataTable de ces lignes distinctes, vous pouvez le faire:

var t2 = new DataTable(); 
t2.Columns.AddRange(table.Columns.Cast<DataColumn>().ToArray()); 
foreach(var r in distinct) 
{ 
    t2.Rows.Add(r); 
} 

Ou s'il serait plus pratique pour travailler avec des objets d'affaires, vous pouvez faire une conversion facile:

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

Mise à jour

Tout ce que vous pouvez faire dans LINQ to Objects peut également être fait sans elle: il faut juste plus de code. Par exemple:

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

Vous pouvez également utiliser une stratégie similaire pour supprimer simplement des lignes en double de la table d'origine au lieu de créer une nouvelle table.

+0

Toute solution non basée sur LINQ? – George2

+1

@ George2:.. voir ma réponse à jour – StriplingWarrior

+0

Merci, réponse à votre question – George2

1

Vous pouvez faire un select into avec une clause group by, donc les doublons ne sont pas créés. Ensuite, déposez l'ancienne table et renommez la table dans laquelle vous avez sélectionné le nom de la table d'origine.

+0

Intéressant! Nous pouvons exécuter SQL dans la table de données? Pouvez-vous me montrer un échantillon s'il vous plaît (ou un document)? Et je particulièrement surpris de voir comment utiliser groupe par pour filtrer les enregistrements en double? – George2

1

Je ferais cela dans la couche de base de données:

SELECT Distinct... 
FROM MyTable 

Ou si vous avez besoin d'agrégats:

SELECT SUM(Field1), ID FROM MyTable 
GROUP BY ID 

Mettez l'instruction SELECT dans une procédure stockée. Puis, dans .net, établissez une connexion à la base de données, appelez la procédure stockée, exécutez .ExecuteNonQuery(). Renvoyez les lignes dans un datatable et renvoyez le datatable à votre interface utilisateur.

+0

Désolé, il n'y a pas de table de base de données liée à la datatable, il est une sortie intermédiaire de mes logiques d'affaires Nous ne peut fonctionner que sur la datatable mémoire Ainsi, votre solution basée sur la base de données ne peut pas être utilisé. Des solutions? – George2

Questions connexes