Вставить строку в БД при использовании многопоточности? - PullRequest
6 голосов
/ 15 апреля 2011

Здесь я использую многопоточность и linq to sql.

Здесь я загружаю свой фрагмент кода:

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

Класс репозитория сообщений

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

Когда я запускаю его без потоков, он работает нормально после включения потока, я получил следующее сообщение об ошибке:

Ошибка: Элемент с таким же ключом уже добавлен.

Заранее спасибо ...:)

Ответы [ 3 ]

3 голосов
/ 16 апреля 2011

Вы не можете использовать LINQ DataContext одновременно:

Ни один из членов экземпляра не гарантированно является потокобезопасным.

Поэтому вынужно либо сериализовать доступ (блокировку), который будет ужасно неэффективным, либо лучше использовать отдельный контекст в каждом потоке:

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

Я также надеюсь, что ради вас в вашем тесте есть реальная логика ожиданиячтобы тестовые потоки завершили работу перед завершением работы ... И, конечно, правильно внедрите IDisposable в своем хранилище и расположите контекст так, чтобы соединение с БД было помещено обратно в пул.

0 голосов
/ 15 апреля 2011

В прошлом у меня были проблемы с LINQ to SQL DataContexts, когда я запоминал объекты, которые я ранее отправил, и пытался вставить их снова при следующей отправке.Похоже, что вы можете столкнуться с чем-то похожим.

Решение, которое я придумал, состояло в том, чтобы избавиться от старого DataContext и начать заново с новым после каждого вызова SubmitChanges ().

0 голосов
/ 15 апреля 2011

Я подозреваю, что вы используете время в качестве первичного ключа или в качестве уникального ограничения.Если это так, то это ваша проблема, вы должны использовать identity или uniqueidentifier.

Идентификация будет более читабельной, так как это будут возрастающие числовые значения.Это также будет полезно, поскольку, как правило, сообщит вам, в каком порядке были вставлены записи, что может пригодиться позже.

Преимущество Uniqueidentifier в том, что вы можете выбрать его заранее, вместо того, чтобы ждать, что даст вам база данных.

Для приложений типа ведения журнала я бы порекомендовал столбец идентификаторов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...