2014-10-29 3 views
2

В последнее время я много читаю об асинхронной платформе Entity Framework, и я ищу правильный способ изменить свои репозитории на асинхронные версии. Теперь они выглядят более или менее следующим образом:Правильный способ реализации репозитория async Entity Framework

public class MyRepo 
{ 
    private DbContext _context; 

    public MyRepo() 
    { 
    _context = new DbContext(); 
    } 

    public int DoSomeStuff(int id) 
    { 
    var item = _context.MyModels.Where(x => x.Id == id).SingleOrDefault();  
    item.MyProperty = "abcd"; 
    return _context.SaveChanges(); 
    } 
} 

Пример вызова этого хранилищу:

var myRepo = new MyRepo(); 
myRepo.DoSomeStuff(1); 
myRepo.DoSomeStuff(2); 

Могу ли я просто изменить функцию DoSomeStuff на:

public async Task<int> DoSomeStuffAsync(int id) 
{ 
    var item = await _context.MyModels.Where(x => x.Id == id).SingleOrDefaultAsync();  
    item.MyProperty = "abcd"; 
    return await _context.SaveChangesAsync(); 
} 

или это неправильно способ обработки экземпляра DbContext, а должен ли он быть:

public async Task<int> DoSomeStuffAsync(int id) 
{ 
    using(var db = new DbContext()) 
    { 
    // ... 
    } 
} 
+1

'new DbContext()' [Почему вы выделяете новые объекты, такие как крестьянин] (http://en.wikipedia.org/wiki/Dependency_injection)? –

+0

Это всего лишь пример, я не принимал DI во внимание, так как это, вероятно, мой следующий вопрос об асинхронных репозиториях :) – Marthijn

ответ

0

Вы можете сделать это в любом случае, в зависимости от семантики, которую вы хотите. Если вы используете общий DbContext, вам просто нужно документировать, что ваши абоненты будут вызывать только один асинхронный метод за раз.

+0

Другие асинхронные методы - это то, что вы * можете * вызывать одновременно, в зависимости от типа базы данных и строку подключения. Это синхронные методы, оба из которых обращаются к базе данных и особенно к методу Dispose(), которые никогда не могут быть безопасными для вызова одновременно с асинхронным методом. – hvd

+1

@hvd: Entity Framework 6 разрешает только одну операцию на 'DbContext' за раз. Поэтому 'waitait.WhenAll (repo.DoSomeStuff1Async(), repo.DoSomeStuff2Async())' будет терпеть неудачу. –

+0

Ого, ты прав, это действительно не так. Я почти уверен, что это было так: 'Task.WhenAll (db.Xs.ToListAsync(), db.Xs.ToListAsync())' будет нестабильным (несколько асинхронных вызовов, создающих сущности), но 'Task.WhenAll (db .Xs.Select (x => x.Id) .ToListAsync(), db.Xs.Select (x => x.Id) .ToListAsync()) 'будет отлично, если базовое соединение поддерживает одновременные запросы. Вторая часть моего комментария стоит, хотя: синхронные методы - не очень хорошая идея позвонить. – hvd

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