LINQ Changeset многопоточность - PullRequest
1 голос
/ 26 мая 2010

Я использую LINQ to SQL, и после отправки некоторых изменений я хочу создать поток, который просматривает все изменения и обновляет наш индекс lucene по мере необходимости. Мой код выглядит примерно так:

(new Thread(() => { UpdateIndex(context.GetChangeSet()); }).Start();

Иногда, хотя я получаю InvalidOperationException, что, я думаю, связано с тем, что context.GetChangeSet () не является поточно-ориентированным, и поэтому, если набор изменений изменяется в одном потоке, когда другой поток перечисляет его, возникают проблемы.

Существует ли "поточно-безопасная" версия GetChangeSet ()? Или каким-то образом я могу сделать ChangeSet.clone () или что-то?

Ответы [ 2 ]

2 голосов
/ 26 мая 2010

Члены экземпляра класса DataContext не являются поточно-ориентированными .

Чтобы избежать условий гонки, вы должны вызвать метод DataContext.GetChangeSet из того же потока, в котором изменения отслеживаются экземпляром DataContext. Например:

public class CustomerDao : IDisposable
{
    private DataContext context;

    public CustomerDao()
    {
        this.context = new DataContext("SomeConnectionString");
    }

    public void Insert(Customer instance)
    {
        this.context.Customers.InsertOnSubmit(instance);
        this.StartUpdateIndex();
        this.context.SubmitChanges();
    }

    public void Delete(Customer instance)
    {
        this.context.Customers.DeleteOnSubmit(instance);
        this.StartUpdateIndex();
        this.context.SubmitChanges();
    }

    public void Dispose()
    {
        if (this.context != null)
        {
            this.context.Dispose();
        }         
    }

    private void StartUpdateIndex()
    {
        ChangeSet changes = this.context.GetChangeSet();
        ThreadPool.QueueUserWorkItem(
            state => this.UpdateIndex((ChangeSet)state), changes); 
    }
}

Предполагается, что методы Insert и Delete вызываются для данного экземпляра класса CustomerDao из одного потока.

0 голосов
/ 26 мая 2010

Мне нужно было только извлечь небольшое количество данных из каждого объекта, так что в итоге я просто извлек текст, поместил его в новый объект и затем отправил этот новый объект. Это избавило меня от многих проблем, связанных с блокировками повсюду, но я думаю, что ответ Энрико, вероятно, «реальный», поэтому его решение помечено как решение.

...