2012-07-18 14 views
7

Ho un problema interessante che gestisce i caratteri "ASCII" a 8 bit in LINQ-to-Entities e spero che qualcuno possa darmi un consiglio.LINQ-to-Entities con dati ASCII a 8 bit

Ho ereditato un database SQL Server 2000 che contiene alcune colonne pseudo-crittografate in cui hanno appena eseguito XOR la ​​stringa con 0xFF. Non so perché e so che è zoppo ma è lì che siamo ora.

Queste colonne sono del tipo di dati SQL char(7) e char(14). Quando XOR usa 0xFF ottieni l'ottavo bit impostato in ogni caso, così finirai con caratteri non ASCII (comunque definiti dalla Microsoft). L'UTF-8 sembra essere indicato qui, ma la decodifica si incasina.

io sono in grado di leggere e decodificare queste stringhe come segue:

  1. Prendi il campo utilizzando LINQ come String.
  2. Prendi un byte[] utilizzando System.Text.Encoding.GetEncoding(1252).GetBytes()
  3. Decode da XOR ogni byte con 0xFF
  4. restituire la stringa decodificata con System.Text.Encoding.GetEncoding(1252).GetString()

Questo funziona perfettamente.

Il problema che sto avendo è che non riesco a mettere una stringa ENCODED a SQL Server usando LINQ.

sto fondamentalmente seguendo il processo inverso e sto facendo:

  1. Ottenere i byte utilizzando ASCIIEncoding.GetBytes(). (Non c'è bisogno di CodePage 1252 qui perché questa è una stringa diritta.)
  2. Codifica i byte con 0xFF.
  3. Restituisce la stringa codificata con GetEncoding(1252).GetString().

Se guardo la mia stringa, è esattamente quello che mi aspetterei. Ma se lo faccio nella mia entità e faccio un SaveChanges() il valore risultante in SQL Server è sempre "?????" di una certa lunghezza.

Sono sicuro che mi manca qualcosa qui ma ho provato tutto quello che riesco a pensare e non riesco a capirlo. Per ora sono appena tornato al vecchio modo di usare un SqlCommand e di fare un UPDATE con le stringhe codificate come SqlParameters. Nessun problema, funziona sempre.

Grazie in anticipo per qualsiasi assistenza.


Aggiornamento:

Ho provato il suggerimento di JamieSee e io non sono nemmeno ottenere una buona decodifica con il suo metodo. Ho:

static void Main(string[] args) 
    { 
     Encoding characterEncoding = Encoding.GetEncoding(28591); 

     HCBPWEBEntities ent = new HCBPWEBEntities(); 

     var encUser = 
      (from users in ent.tblEmployer 
      where users.ipkEmpId == 357 
      select users.sKey).First(); 

     Console.Out.WriteLine("Original XOR Encoded PW: {0}", encUser.ToString().Trim()); 

     byte[] originalBytes = (from character in characterEncoding.GetBytes(encUser.ToString().Trim()) 
           select (byte)(character)).ToArray(); 

     Console.Write("Original Bytes:\t"); 
     foreach (byte b in originalBytes) 
     { 
      Console.Write("{0:x} ", b); 
     } 
     Console.WriteLine(String.Empty); 

     byte[] decodedBytes = (from character in characterEncoding.GetBytes(encUser.ToString().Trim()) 
           select (byte)(character^0xFF)).ToArray(); 

     Console.Write("Decoded Bytes:\t"); 
     foreach (byte b in decodedBytes) 
     { 
      Console.Write("{0:x} ", b); 
     } 
     Console.WriteLine(String.Empty); 

     string decoded = characterEncoding.GetString(decodedBytes); 
     Console.WriteLine("Decoded PW: {0}", decoded); 

     ent.Dispose(); 
    } 

Ma il risultato di che sono:

originale XOR Encoded PW: z?o> Byte originali: 7a 9d 6f 3e Decoded Bytes: 85 62 90 c1 Decoded PW: b Un

La password è in realtà "ABCD"

+0

Si prega di catturare l'SQL eseguito da L2S utilizzando SQL Profiler e post-it. (È estremamente facile farlo.) – usr

+0

Uso LINQ-to-Entities e non LINQ-to-SQL ma acquisire l'SQL usando Profiler è una buona idea. Lo sistemerò e vedrò cosa dice. Ma la mia ipotesi è che mostrerà che SQL sta memorizzando esattamente quello che viene detto di memorizzare. Credo davvero che il problema sia nel mappare i caratteri non ASCII da Entity FW a SQL. – user1536209

+0

Quali sono le tue regole di confronto per il database in questione? Puoi trovarlo con 'SELECT nome_collazione FROM sys.databases WHERE name = 'mydatabase''. – JamieSee

risposta

1

Non utilizzare pagina di codice 1252 uso Encoding.GetEncoding(28591)? (iso-8859-1) o Encoding.GetEncoding(850) (ibm850), ognuno dei quali offre set di caratteri basati su ASCII a 8 bit.

Ecco qualche rapido & codice di sporco, che si può provare con diverse codifiche, per dimostrare il problema e la soluzione:

public static void Main() 
{ 
    Encoding characterEncoding = Encoding.GetEncoding(28591); 

    string original = "This is some bogus data to test the problem."; 
    Console.WriteLine("Original String: {0}", original); 

    Console.Write("Original Bytes: "); 
    foreach (byte b in characterEncoding.GetBytes(original)) 
    { 
     Console.Write("{0:x}", b); 
    } 
    Console.WriteLine(); 

    byte[] encodedBytes = (from character in characterEncoding.GetBytes(original) 
          select (byte)(character^0xFF)).ToArray(); 

    Console.Write("Encoded Bytes: "); 
    foreach (byte b in encodedBytes) 
    { 
     Console.Write("{0:x}", b); 
    } 
    Console.WriteLine(); 

    string encoded = characterEncoding.GetString(encodedBytes); 

    byte[] decodedBytes = (from character in characterEncoding.GetBytes(encoded) 
          select (byte)(character^0xFF)).ToArray(); 

    Console.Write("Decoded Bytes: "); 
    foreach (byte b in decodedBytes) 
    { 
     Console.Write("{0:x}", b); 
    } 
    Console.WriteLine(); 

    string decoded = characterEncoding.GetString(decodedBytes); 

    Console.WriteLine("Decoded String: {0}", decoded); 
}