2016-04-26 4 views
2

Я пишу приложение C# .NET4.5 Console, ориентированное на Entity Framework 6.1.3. Я использую единицы работы парадигмы следующим образом:Поддерживает ли Entity Framework многопоточность?

public class UnitOfWork : IUnitOfWork, IDisposable 
{ 
    private readonly DataContext _context; 
    private readonly List<object> _repositories = new List<object>(); 
    public UnitOfWork(DataContext context) 
    { 
     _context = context; 
     _context.Configuration.LazyLoadingEnabled = false; 
    } 

    public IRepository<T> GetRepository<T>() where T : class 
    { 
     //try to get existing repository 
     var repo = (IRepository<T>)_repositories.SingleOrDefault(r => r is IRepository<T>); 
     if (repo == null) 
     { 
      //if not found, create it and add to list 
      _repositories.Add(repo = new EntityRepository<T>(_context)); 
     } 
     return repo; 
    } 

    public int Commit() 
    { 
     return _context.SaveChanges(); 
    } 


    public bool AutoDetectChanges 
    { 
     get { return _context.Configuration.AutoDetectChangesEnabled; } 
     set { _context.Configuration.AutoDetectChangesEnabled = value; } 
    } 

И мой Repository так:

public class EntityRepository<T> : IRepository<T> where T: class 
    { 
     protected readonly DbContext Context; 
     protected readonly DbSet<T> DbSet; 
    public EntityRepository(DbContext context) 
    { 
     Context = context;    
     DbSet = Context.Set<T>(); 
    } 

    public IQueryable<T> All() 
    { 
     return DbSet; 
    } 
    ….. other functions…. 

    public virtual void Add(T entity) 
    {   
     DbEntityEntry dbEntityEntry = Context.Entry(entity); 
     if (dbEntityEntry.State != EntityState.Detached) 
     { 
      dbEntityEntry.State = EntityState.Added; 
     } 
     else 
     { 
      DbSet.Add(entity); 
     } 
    } 
    } 

Я называю это так:

var rep = _uow.GetRepository<TableOfPies>(); 
rep.Add(Pie); 
_uow.Commit(); 

My Console приложение имеет несколько потоки, каждый из которых в какой-то момент захочет обновить/изменить/добавить в те же таблицы в моей облачной базе данных SQL Server.

Я реализовал потокобезопасный код для моего другого кода, используя блокировки, но я не знаю, как я могу сделать Entity потокобезопасным? Прямо сейчас, я получаю следующее сообщение об ошибке:

INNER EXCEPTION: New transaction is not allowed because there are other threads running in the session.

Я смотрел онлайн и не смог найти много о Сущности и многопоточности. Я слышал, что Entity не поддерживает многопоточные приложения, но находит, что слышал, чтобы верить. Любые указатели будут очень благодарны.

+0

Я бы отметил, что многопоточность только улучшает задачи _CPU-bound_. Поскольку задачи базы данных, как правило, связаны с вводом-выводом (тем более для «облачных» баз данных) многопоточность может не очень помочь и даже может быть _worse_, если накладные расходы нескольких потоков пересиливают любую выгоду. –

+0

@DStanley Это не совсем так. Я использую многопоточность для задач ввода-вывода все время и нахожу огромное преимущество. Преимущество состоит в том, что пока вы ждете ответа на один запрос, вы можете готовить и отправлять следующее. Конечно, это не зависит от более чем одного потока. Это больше похоже на многозадачность, хотя она часто выглядит одинаково. Мне очень нравится новая библиотека задач в .NET для этого. Я код, как будто это многопоточность, но структура заботится о том, сколько потоков оно фактически использует. –

ответ

5

Документация для DataContext состояний:

Any instance members are not guaranteed to be thread safe.

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

Вам нужно будет создать новый экземпляр DataContext в каждом потоке.

+0

Ничего себе. Это простое решение ... Я думал, мне придется вернуться к SQL :). Один DataContext для каждого потока. Ницца. Я попробую. –

Смежные вопросы