1

Я работаю над веб-приложением asp.net mvc5 + Entity Framework 6. И я хочу иметь класс модели репозитория внутри моего приложения. В настоящее время я следую этому подходу, чтобы иметь методы асинхронного действия и класс модели асинхронного репозитория.написание async Методы репозитория внутри моего веб-приложения asp.net mvc5

, например, у меня есть следующий репозиторий метод сохранения: -

public class Repository 
    { 

     private Entities t = newEntities(); 

     public async Task Save() 
     { 
      await t.SaveChangesAsync(); 
     } 

который я звоню из моих методов действия следующим образом: -

Repository repository = new Repository(); 
public async Task<ActionResult> GetResourceByName(string resourcename) 
     { 
     await repository.Save(); 
     } 

так это правильный подход? как я делаю следующее: -

  1. я определить метод репозитория как Task & также способ действий в качестве задачи. поэтому у меня есть оба из них как Задача (ы).?

  2. Я использую await дважды по методу действия (при вызове метода репо) и в репозитории? так ли это await избыточным?

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

ответ

2
  1. Q1: Да, оба должны возвращать Задачу, и так оно и должно быть, и все в порядке.
  2. Q2: Да, оба должны иметь ожидание (если у вас больше слоев, тогда все вызовы функций во всех этих слоях должны были бы ждать).

В основном: После того, как вы идете асинхронной/Await, вся цепочка вызовов должна быть асинхронной/Await, чтобы избежать проблем, связанных с резьбой ...

Если вы не ждать, то, что называется: «Огонь и Forget ", который не рекомендуется, потому что тогда этот запрос будет возвращен пользователю с сообщением об успешном завершении, но в более позднее время вызов, который вы сделали без ожидания, может выйти из строя и выбросить исключение, и вы не будете иметь никакого представления о том, что это исключение ...

+0

Я полностью осведомлен о «Огне и забыл». Но все же я не понял, почему мне нужно иметь ожидание внутри моего действия. например, если я заменил это «ожидание репозитория.Save()» с «repository.Save() // no await», то defualt asp.net mvc не будет продолжать выполнение, если не получит результат. и поскольку метод репо использует ожидание «ждут t.SaveChangesAsync();» то он должен подождать до завершения сохранения, это правильно?другими словами, метод действия не будет продолжать выполнение, если только «ждут t.SaveChangesAsync();» полностью, так почему я должен ждать и уже ожидаемый метод! –

+0

Это неправда. Если вы не ожидаете, что он не будет ждать, и вы не узнаете результат звонка ... – Aram

0

Чтобы ответить на ваши вопросы:

  1. Да, они должны оба вернуть Задачи.
  2. Да, await имеют смысл. Нет, они не избыточны.

Чтобы понять, почему вы мощь (не обязательно) нужно await дважды, я предлагаю вам взглянуть на эту статью, которая дает довольно наглядный пример того, как и почему это работает:

C# async and await: Why Do We Need Them?

Если вы хотите использовать репозиториев и может рассмотреть вопрос об использовании услуг для вас бизнес-логики, я бы порекомендовал вам проверить этот проект, который легко расширяемым и родовое:

URF - Unit of Work & Repositories Framework

Прежде чем вы начнете разрабатывать все с нуля, вы должны это проверить. Мне очень нравится этот проект!

+0

спасибо за ответ, который вы упомянули, что мне нужно использовать ожидание дважды; о методе действия & в репозитории. но я не уверен, почему мне нужно ждать уже ожидаемого метода. Поскольку, поскольку я ожидаю сущности.savechnagesasync() в классе репозитория, то почему я должен использовать ожидание при вызове уже ожидаемого метода? –

+0

Я отредактировал свой ответ, чтобы добавить дополнительную информацию о 'await'. – Maxime

2

В отличие от обоих ответов два awaits не нужны. await и async необходимы, только если вам нужен результат от Task, прежде чем продолжить. Если вам не нужен этот результат, вам не нужно указывать свой метод async.

Это означает, что этот метод ...

public async Task Save() 
{ 
    await t.SaveChangesAsync(); 
} 

Может быть упрощен в

public Task Save() 
{ 
    return t.SaveChangesAsync(); 
} 

Даже если это функционально то же, мне нравится второй вариант, потому что это показывает, что признание Task является асинхронная работа и async/await - только сигналы компилятору, ожидающие завершения этой работы.

+0

Остерегайтесь того, что в случае исключения внутри трассировка стека 't.SaveChangesAsync()' не будет отображать 'Save()' while, если используется 'await'. –

+0

@ Спасибо за ответ, вы упомянули «Если вам не нужен этот результат, вам не нужно указывать свой асинхронный метод». но я думаю, что вы имеете в виду «Если вам не нужен этот результат, вам не нужно указывать свой метод» это правильно, так как ожидание заставит систему ждать завершения кода до продолжения. –

+0

@Shoe «В отличие от обоих ответов два ожидания не нужны». Ответы не говорят, что они «необходимы», говорят, что это не избыточно. Это большое различие. – Maxime

1

Независимо от других ответов, вот почему вы должны использовать await и другие.

ASP.NET имеет контекст синхронизации, который будет записан на каждом await, а продолжение (остальная часть метода async) будет опубликовано для этого контекста. Это означает не только переключение потоков, но и переключение на поток с помощью контекста ASP.NET.

Если суффикс ваших асинхронных вызовов (те, с await вызовом ConfigureAwait(false) переключение контекста ASP.NET не произойдет (хотя переключение нити будет).

Поскольку вид двигателю действия, скорее всего, нужно контекст ASP.NET, вы не можете использовать ConfigureAwait(false) на методе действия MVC Но вы должны использовать на всех методов, вызываемых ею

Таким образом, ваш код должен быть что-то вроде этого:..

public class Repository 
{ 
    private Entities t = new Entities(); 
    public async Task SaveAsync() 
    { 
     await t.SaveChangesAsync().ConfigureAwait(false); 
    } 
} 


Repository repository = new Repository(); 
public async Task<ActionResult> GetResourceByName(string resourcename) 
{ 
    await repository.SaveAsync(); 
} 

Поскольку у вас может не быть контекста ASP.NET после await с вызовом ConfigureAwait(false), вы должны передать в качестве аргументов все, что вам нужно, из контекста ASP.NET.

+0

спасибо за ответ .. но я не получил ур точку, почему мне нужно добавить «ConfigureAwait (false)»; внутри SaveAsync? в моем случае я не использую его, и я не нашел никакой проблемы, поэтому, если я не использую его, что это будет причиной? –

+0

Пожалуйста, прочитайте [эти статьи] (https://docs.com/paulo-morgado/8860/async-await-general), чтобы узнать, как работает «async-await». –

+0

, поэтому вы подразумеваете, что мне нужно использовать «ConfigureAwait (false)»; ?? –

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