2009-08-05 6 views
2

J'utilise VSTS 2008 + C# + .Net 3.0. J'ai deux cordes d'entrée, je pense qu'ils sont différents. Mais le code C# suivant pense qu'ils sont identiques et renvoie System.Data.ConstraintException, indique que le nom de colonne est contraint à être unique, mais que la valeur existe déjà. Des idées ce qui ne va pas?Problème de duplication de chaîne C#

Voici mon code et mes cordes d'entrée,

vue Hex de mes cordes d'entrée,

http://i30.tinypic.com/2anx2b.jpg

vue Bloc-notes de mes chaînes d'entrée,

http://i30.tinypic.com/2q03hn4.jpg

Mon code,

static void Main(string[] args) 
    { 
     string[] buf = new string[] { "2ch", "2ch" }; 

     DataTable bulkInserTable = new DataTable("BulkTable"); 
     DataColumn column = null; 
     DataRow row = null; 

     column = new DataColumn(); 
     column.DataType = System.Type.GetType("System.String"); 
     column.ColumnName = "Name"; 
     column.ReadOnly = true; 
     column.Unique = true; 
     bulkInserTable.Columns.Add(column); 

     foreach (string item in buf) 
     { 
      row = bulkInserTable.NewRow(); 
      row["Name"] = item; 
      bulkInserTable.Rows.Add(row); 
     } 
    } 

EDIT 1:

Ma confusion est, pourquoi C# Dictionnaire pense qu'ils sont différents, mais DataSet pense qu'ils sont de même. Toute solution pour rendre le comportement cohérent? Voici mon code pour prouver que C# Dictionary pense qu'ils sont différents, le tableau buf de retour est de deux éléments.

  Dictionary<string, bool> dic = new Dictionary<string, bool>(); 
      foreach (string s in buf) 
      { 
       dic[s] = true; 
      } 
      buf = new List<string>(dic.Keys).ToArray(); // we got two strings here, other than one, which proves Dictionary thinks the two strings are different. 
+1

Les formes "normales" et pleine/demi-largeur des caractères latins sont généralement considérées comme équivalentes si vous traitez du texte. – Joey

+0

Merci Johannes, je veux en savoir plus sur ce que signifie exactement les formes de latin et de demi-largeur, pourriez-vous recommander quelques lectures? – George2

Répondre

5

bien pour commencer, vous devez vous codez échantillon à:

foreach (string item in buf) 
{ 
    row = bulkInserTable.NewRow(); 
    row["Name"] = item; 
    bulkInserTable.Rows.Add(row); 
} 

Bien que présente encore la question au moins il est pour la vraie raison

La raison en est que, Lors de la création d'un tableau de données, les options de comparaison par défaut en vigueur sont les suivantes:

this._compareFlags = CompareOptions.IgnoreWidth 
        CompareOptions.IgnoreKanaType | 
        CompareOptions.IgnoreCase; 

Depuis le Ignorer la largeur:

Indique que la comparaison de chaînes doit ignorer la largeur du caractère. Par exemple, les caractères katakana japonais peuvent être écrits en pleine largeur ou en demi-largeur. Si cette valeur est sélectionnée, les caractères katakana écrits en pleine largeur sont considérés comme égaux aux mêmes caractères écrits en demi-largeur.

System.Globalization.CultureInfo.CurrentCulture.CompareInfo.Compare(
    "2ch", "2ch", System.Globalization.CompareOptions.IgnoreWidth); 

renvoie 0, soit identique

Je vous suggère fortement ne considèrent ces valeurs identiques ou causer la confusion la ligne si vous voulez vraiment changer:

//CaseSensitive property uses this under the hood 
internal bool SetCaseSensitiveValue(
    bool isCaseSensitive, bool userSet, bool resetIndexes) 
{ 
    if (!userSet && (
     this._caseSensitiveUserSet || (this._caseSensitive == isCaseSensitive))) 
    { 
     return false; 
    } 
    this._caseSensitive = isCaseSensitive; 
    if (isCaseSensitive) 
    { 
     this._compareFlags = CompareOptions.None; 
    } 
    else 
    { 
     this._compareFlags = CompareOptions.IgnoreWidth | 
          CompareOptions.IgnoreKanaType | 
          CompareOptions.IgnoreCase; 
    } 
    if (resetIndexes) 
    { 
     this.ResetIndexes(); 
     foreach (Constraint constraint in this.Constraints) 
     { 
      constraint.CheckConstraint(); 
     } 
    } 
    return true; 
} 

Ainsi, vous pouvez ignorer les cas et désactiver totalement les options de comparaison complexes.

Si vous voulez faire un dictionnaire avec le même comportement utiliser le comparateur suivant:

public class DataTableIgnoreCaseComparer : IEqualityComparer<string> 
{ 
    private readonly System.Globalization.CompareInfo ci = 
     System.Globalization.CultureInfo.CurrentCulture.CompareInfo; 
    private const System.Globalization.CompareOptions options = 
     CompareOptions.IgnoreCase | 
     CompareOptions.IgnoreKanaType | 
     CompareOptions.IgnoreWidth; 

    public DataTableIgnoreCaseComparer() {} 

    public bool Equals(string a, string b) 
    { 
     return ci.Compare(a, b, options) == 0; 
    } 

    public int GetHashCode(string s) 
    { 
     return ci.GetSortKey(s, options).GetHashCode(); 
    } 
} 
+0

Bonne prise, j'ai corrigé mon code. – George2

+0

J'ai posté ma confusion supplémentaire au sujet du comportement incohérent entre C# Dictionary et C# DataSet pour vérifier l'unicité de la chaîne, des solutions pour rendre le comportement cohérent? – George2

+0

Merci ShuggyCoUk. Je pense les traiter de la même manière en faisant plus de sens. Comment utiliser votre fonction System.Globalization.CultureInfo.CurrentCulture.CompareInfo.Compare ci-dessus pour vérifier l'unicité des chaînes, c'est-à-dire pour un tableau de chaînes d'entrée, je veux produire des chaînes d'unicité ignorent de la largeur. – George2

5

Où placez-vous la chaîne dans la rangée? Il me semble que vous créez des lignes vides et en insérant 2 d'entre eux?

Quelque chose comme ça?

 foreach (string item in buf) 
     { 
      row = bulkInserTable.NewRow(); 
      row["Name"] = item;//Set the data<------------ 
      bulkInserTable.Rows.Add(row); 
     } 
+0

Je crée une table en mémoire, puis je l'insère en masse dans la base de données principale. J'ai posté ma confusion supplémentaire sur le comportement incohérent entre C# Dictionary et C# DataSet pour vérifier l'unicité de la chaîne, des solutions pour rendre le comportement cohérent? – George2

+0

Bonne prise, j'ai corrigé mon code. – George2

1

Il semble que le codage est différent sur la deuxième chaîne. Lors du débogage, la deuxième chaîne revient en tant que poubelle. Si je supprime la deuxième chaîne et entrez "2 c h" dans Visual Studio, cela fonctionne correctement.

+0

Merci Jonathan, mais je ne peux pas supprimer la 2ème chaîne pour faire une solution. Je dois faire face aux deux formes. J'ai posté ma confusion supplémentaire sur le comportement incohérent entre C# Dictionary et C# DataSet pour vérifier l'unicité de la chaîne, des solutions pour rendre le comportement cohérent? – George2

6

Cela dépend de ce que vous entendez par "le même".

Les deux chaînes ont des valeurs Unicode différentes, mais je suppose que dans certaines règles de normalisation, elles seraient identiques. Juste pour que d'autres puissent le reproduire facilement sans problèmes de couper et coller, la deuxième chaîne est:

"\uff12\uff43\uff48" 

Ce sont les versions "full width" de « 2ch ». EDIT: Pour répondre à votre modification, il est clair que le DataSet utilise une autre idée d'égalité, tandis que si vous ne fournissez rien de spécifique, Dictionary utilisera des comparaisons ordinales (fournies par string lui-même).

EDIT: Je suis assez sûr que le problème est que le DataTable utilise CompareOptions.IgnoreWidth:

using System; 
using System.Data; 
using System.Globalization; 

class Test 
{ 
    static void Main() 
    { 
     string a = "2ch"; 
     string b = "\uff12\uff43\uff48"; 

     DataTable table = new DataTable();    
     CompareInfo ci = table.Locale.CompareInfo; 

     // Prints 0, i.e. equal 
     Console.WriteLine(ci.Compare(a, b, CompareOptions.IgnoreWidth)); 
    } 
} 

EDIT: Si vous définissez CaseSensitive propriété du DataTable à vrai, je pense qu'il se comportera de la Identique à Dictionary.

+0

Merci Jon, j'ai posté ma confusion supplémentaire au sujet du comportement incohérent entre C# Dictionary et C# DataSet pour vérifier l'unicité de la chaîne, des solutions pour rendre le comportement cohérent? – George2

+0

Comment rendre le comportement cohérent? J'utilise à la fois Dictionary et DataSet dans mon programme et ils produisent des résultats différents ... Très bizarre. Peu importe qu'ils soient identiques ou différents, je veux avoir le même comportement. Des solutions? – George2

+0

Merci Jon, définissez la propriété CaseSensitive DataTable à true résoudre mon problème. Une autre question, je pense que les deux chaînes sont des versions pleine largeur ou demi largeur de chaîne, ils ne sont pas de différentes chaînes sensibles à la casse - majuscules et minuscules, pourquoi la propriété CaseSensitive qui contrôle les majuscules et minuscules questions? – George2