2009-08-05 1 views
2

Ich verwende VSTS 2008 + C# +. Net 3.0. Ich habe zwei Eingabezeichenfolgen, ich denke, sie sind unterschiedlich. Aber der folgende C# -Code denkt, dass sie identisch sind und System.Data.ConstraintException auslöst, da Spaltenname eindeutig ist, aber Wert existiert bereits. Irgendwelche Ideen was ist falsch?C# String-Duplizierungsproblem

Hier ist mein Code und meine Eingabezeichenfolgen,

Hex Ansicht meiner Eingabezeichenfolgen,

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

Notepad Blick auf meine Eingabe-Strings,

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

Meine 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:

Meine Verwirrung ist, warum C# Wörterbuch denkt, dass sie unterschiedlich sind, aber DataSet denkt, dass sie aus dem gleichen sind. Irgendeine Lösung, um das Verhalten konsistent zu machen? Hier ist mein Code zu beweisen, C# Dictionary denkt, dass sie unterschiedlich sind, ist das Return-Buf-Array von zwei Elementen.

  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

Die "normalen" und vollen/halben Breite Formen der lateinischen Zeichen werden in der Regel als gleichwertig betrachtet, wenn Sie mit Text zu tun haben. – Joey

+0

Danke Johannes, ich möchte mehr darüber lernen, was genau lateinische Voll- und Halbseitenformen bedeutet, könntest du einige Lesungen empfehlen? – George2

Antwort

5

gut für einen Start benötigen Sie Sie Codebeispiel zu sein:

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

Obwohl das immer noch das Problem zumindest zeigt es für den wahren Grund

Der Grund dafür, dass ist, Beim Erstellen einer Datentabelle sind die folgenden Standardvergleichsoptionen gültig:

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

Von der docs Breite ignorieren:

Gibt an, dass der Zeichenfolgenvergleich die Zeichenbreite ignorieren muss. Zum Beispiel können japanische Katakana-Zeichen als volle oder halbe Breite geschrieben werden. Wenn dieser Wert ausgewählt ist, werden die Katakana-Zeichen, die als volle Breite geschrieben werden, als die gleichen Zeichen angesehen, die als halbe Breite geschrieben sind.

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

0 zurück, dh identische

empfehle ich Sie solche Werte identisch oder verursachen weitere Verwirrung der ganzen Linie jedoch berücksichtigen tun, wenn Sie es wirklich wollen sich ändern:

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

So können Sie Groß- und Kleinschreibung ignorieren und die komplexen Vergleichsoptionen vollständig deaktivieren.

Wenn Sie ein Wörterbuch mit dem gleichen Verhalten machen, die folgende Vergleich verwenden:

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

Guter Fang, ich habe meinen Code korrigiert. – George2

+0

Ich habe meine weitere Verwirrung über inkonsistentes Verhalten zwischen C# Dictionary und C# DataSet gepostet, um über die String-Eindeutigkeit zu prüfen, irgendwelche Lösungen, um das Verhalten konsistent zu machen? – George2

+0

Danke ShuggyCoUk. Ich denke, behandle sie gleich, mache mehr Sinn. Wie Sie Ihre obige Funktion System.Globalization.CultureInfo.CurrentCulture.CompareInfo.Compare verwenden, um die Eindeutigkeit von Zeichenfolgen zu überprüfen, d. H. Für ein Array von Eingabezeichenfolgen möchte ich Eindeutigkeitszeichenfolgen ausgeben, die Breite ignorieren. – George2

5

Wo setzen Sie die Zeichenfolge in die Zeile? Es sieht für mich so aus, als würden Sie leere Zeilen erstellen und 2 von ihnen einfügen?

So ähnlich?

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

Ich erstelle eine speicherinterne Tabelle und führe dann eine Masseneinfügung in die Backend-Datenbank durch. Ich habe meine weitere Verwirrung über inkonsistentes Verhalten zwischen C# Dictionary und C# DataSet gepostet, um über die String-Eindeutigkeit zu prüfen, irgendwelche Lösungen, um das Verhalten konsistent zu machen? – George2

+0

Guter Fang, ich habe meinen Code korrigiert. – George2

1

Es sieht aus wie die Codierung auf der zweiten Saite unterscheidet. Beim Debuggen kommt die zweite Zeichenfolge als Müll zurück. Wenn ich die zweite Zeichenfolge lösche und "2 C h" in Visual Studio eintrage, funktioniert es richtig.

+0

Danke Jonathan, aber ich kann den 2. String nicht löschen, um eine Lösung zu finden. Ich muss mit beiden Formen umgehen. Ich habe meine weitere Verwirrung über inkonsistentes Verhalten zwischen C# Dictionary und C# DataSet gepostet, um über die String-Eindeutigkeit zu prüfen, irgendwelche Lösungen, um das Verhalten konsistent zu machen? – George2

6

Es hängt davon ab, was Sie mit "das gleiche" meinen.

Die zwei Zeichenfolgen haben unterschiedliche Unicode-Werte, aber ich vermute, dass sie unter einigen Normalisierungsregeln identisch wären. Genau so dass andere es leicht, ohne Ausschneiden und Einfügen Probleme wiedergeben können, die zweite Zeichenfolge ist:

"\uff12\uff43\uff48" 

Dies sind die "full width" Versionen von „2-Kanal“.

EDIT: auf Ihre bearbeiten zu reagieren, deutlich die DataSet verwendet eine andere Idee der Gleichheit, während, wenn Sie etwas Bestimmtes bieten, Dictionary Ordnungs Vergleiche verwenden (wie sich durch String zur Verfügung gestellt).

EDIT: Ich bin mir ziemlich sicher, dass das Problem ist, dass die Datatable CompareOptions.IgnoreWidth verwendet, ist:

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: Wenn Sie die DataTable ‚s CaseSensitive Eigenschaft auf true gesetzt ist, vermute ich es das verhalten wie Dictionary.

+0

Dank Jon, habe ich meine weitere Verwirrung über inkonsistentes Verhalten zwischen C# Dictionary und C# DataSet gepostet, um über String-Eindeutigkeit zu überprüfen, irgendwelche Lösungen, um das Verhalten konsistent zu machen? – George2

+0

Wie wird das Verhalten konsistent gemacht? Ich verwende sowohl Dictionary und DataSet in meinem Programm und sie produzieren unterschiedliche Ergebnisse ... Sehr seltsam. Egal, ob sie gleich oder verschieden sind, ich möchte das gleiche Verhalten haben. Irgendwelche Lösungen? – George2

+0

Dank Jon, legen Sie die CaseSensitive-Eigenschaft der DataTable auf True, um mein Problem zu lösen. Eine weitere Frage, ich denke, die beiden Strings sind volle Breite oder halbe Breite Versionen von String, sie sind nicht von verschiedenen Groß- und Kleinschreibung Zeichenfolgen - Groß- und Kleinschreibung, warum CaseSensitive-Eigenschaft, die Groß- und Kleinschreibung Angelegenheiten? – George2