2012-07-18 15 views
7

Tengo un problema interesante al manejar caracteres "ASCII" de 8 bits en LINQ-to-Entities y espero que alguien me pueda dar un consejo.LINQ-to-Entities con datos ASCII de 8 bits

He heredado una base de datos SQL Server 2000 que tiene algunas columnas pseudo-encriptadas donde simplemente XOR'd la cadena con 0xFF. No sé por qué y sé que es cojo, pero ahí es donde estamos ahora.

Estas columnas son del tipo de datos SQL char(7) y char(14). Cuando utiliza XOR usando 0xFF, obtiene el 8º bit establecido en cada caso, por lo que termina con caracteres que no son ASCII (por definición de Microsoft de todos modos). UTF-8 parece estar indicado aquí pero la decodificación se arruina.

Soy capaz de leer y decodificar estas cadenas de la siguiente manera:

  1. Consigue el campo utilizando LINQ como String.
  2. Obtener una usando System.Text.Encoding.GetEncoding(1252).GetBytes()
  3. Decode byte[] aplicándole una operación XOR con cada byte 0xFF
  4. devolver la cadena decodificada con System.Text.Encoding.GetEncoding(1252).GetString()

Esto funciona perfectamente.

El problema que tengo es que parece que no puedo devolver una cadena ENCODED a SQL Server utilizando LINQ.

estoy siguiendo básicamente el proceso inverso y estoy haciendo:

  1. Obtener los bytes utilizando ASCIIEncoding.GetBytes(). (No es necesario CodePage 1252 aquí, ya que es una cadena recta.)
  2. Codifica los bytes con 0xFF.
  3. Devuelve la cadena codificada con GetEncoding(1252).GetString().

Si miro mi cuerda, es exactamente lo que esperaría. Pero si incluyo eso en mi entidad y hago un SaveChanges(), el valor resultante en SQL Server es siempre "?????" de cierta longitud.

Estoy seguro de que me falta algo aquí, pero he intentado todo lo que puedo pensar y no puedo conseguirlo. Por ahora, simplemente volví a la forma anticuada de usar un SqlCommand y hacer una ACTUALIZACIÓN con las cadenas codificadas como SqlParameters. No hay problema allí, funciona todo el tiempo.

Gracias de antemano por su asistencia.


Actualización:

Probé la sugerencia de JamieSee y ni siquiera estoy poniendo buena decodificación con su método. Tengo:

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

Pero el resultado de que son:

original XOR codificado PW: z?o> Bytes originales: 7a 9d 6f 3e Decoded Bytes: 85 62 90 c1 Decoded PW: b Un

La contraseña es en realidad "ABCD"

+0

favor capturar el SQL ejecutado por L2S utilizando SQL y que lo ponga. (Es extremadamente fácil hacerlo.) – usr

+0

Estoy utilizando LINQ-to-Entities y no LINQ-to-SQL, pero capturar el SQL usando Profiler es una buena idea. Lo instalaré y veré lo que dice. Pero supongo que mostrará que SQL está almacenando exactamente lo que se le dice que almacene. Realmente creo que el problema está en mapear los caracteres no ASCII de Entity FW a SQL. – user1536209

+0

¿Cuál es su clasificación para la base de datos en cuestión? Puede encontrarlo con 'SELECCIONAR colación_nombre FROM sys.databases WHERE name = 'mydatabase''. – JamieSee

Respuesta

1

No utilice la página de códigos 1252 Encoding.GetEncoding(28591) uso? (iso-8859-1) o Encoding.GetEncoding(850) (ibm850), cualquiera de los cuales le ofrece juegos de caracteres basados ​​en ASCII de 8 bits.

Aquí hay algo de código rápida & sucia, que se puede probar con diferentes codificaciones, para demostrar su problema y la solución:

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