2011-04-15 12 views
6

Aquí estoy usando multi threading y linq a sql.¿Insertar fila en DB mientras usa multiprocesos?

Aquí subo mi fragmento de código: Clase Repositorio

public class PostService 
{ 
    MessageRepository objFbPostRespository = new MessageRepository(); 
    public void callthreads() 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      Thread th = new Thread(postingProcess); 
      th.Start(); 
     } 
    } 

    public void postingProcess() 
    { 
     objFbPostRespository.AddLog("Test Multithread", DateTime.Now); 
    } 
} 

mensaje

class MessageRepository 
{   
    DataClassesDataContext db_Context = new DataClassesDataContext(); 
    public void AddLog(string Message, DateTime CurrentDateTime) 
    { 
     FbMessgaeLog FbMessage = new FbMessgaeLog 
     { 
      Message = Message, 
      Time = CurrentDateTime     
     }; 
     db_Context.FbMessgaeLogs.InsertOnSubmit(FbMessage); 
     db_Context.SubmitChanges(); 
    } 
} 

cuando lo ejecuto sin hilos, entonces está bien el trabajo después de incluir hilo me dieron msg siguientes errores:

Error: Un elemento con la misma clave ya tiene sido agregado.

Gracias de antemano ... :)

+1

¿Qué utiliza su base de datos como clave aquí? – Jens

+0

@Jens Supongo que es una columna de identidad de base de datos y ese es el problema principal – Manatherin

+2

¿cuál es su requisito que lo haga elegir el enfoque de subprocesamiento múltiple? ¿no puedes usar una cola para presionar elementos para escribir y regresar instantáneamente, y dejar que un trabajador de fondo haga el trabajo de manera secuencial? –

Respuesta

3

No se puede utilizar un LINQ DataContext de forma concurrente:

Any instance members are not guaranteed to be thread safe.

lo tanto es necesario ya sea en serie el acceso (bloqueo) que será terriblemente ineficiente, o mejor utilizar un contexto separada en cada hilo:

public class PostService 
{ 
    public void callthreads() 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      Thread th = new Thread(postingProcess); 
      th.Start(); 
     } 
    } 

    public void postingProcess() 
    { 
     using (MessageRepository objFbPostRespository = new MessageRepository()) 
     { 
      objFbPostRespository.AddLog("Test Multithread", DateTime.Now); 
     } 
    } 
} 

También espero, por su propio bien, que su prueba tenga lógica real para esperar que los hilos de prueba se completen antes de apagarse ... Y, por supuesto, implemente correctamente IDisposable en su repositorio y elimine el contexto para que el DB connecti en ser colocado de nuevo en la piscina.

0

que sospechan que está utilizando el tiempo como la clave principal o como una restricción única. Si es así, ese es su problema, debe usar un identity o un uniqueidentifier.

La identidad será más legible, ya que será valores numéricos ascendentes. También será útil, ya que generalmente le indicará en qué orden se insertaron los registros, lo que puede ser útil más adelante.

Uniqueidentifier tiene la ventaja de que puede elegirlo de antemano en lugar de esperar a ver qué le proporciona la base de datos.

Para una aplicación de tipo de registro, recomendaría una columna de identidad.

0

He tenido problemas en el pasado con LINQ to SQL DataContexts recordando objetos que había enviado anteriormente, y tratando de insertarlos nuevamente la próxima vez que lo envíe. Parece que podrías encontrar algo similar.

La solución que se me ocurrió fue eliminar el antiguo DataContext y comenzar de nuevo con uno nuevo después de cada llamada a SubmitChanges().

Cuestiones relacionadas