Как использовать AsNoTracking в слое сервиса - PullRequest
0 голосов
/ 17 мая 2018

Я обычно использую AsNoTracking, когда не собираюсь ничего писать. Как я должен справиться с этим в моем слое обслуживания, где dbContext скрыт за этим? (Я рассматриваю ядро ​​EF как хранилище, потому что оно хранилище)

public class SomeService
{
    //...

    public SomeEntity GetById(int id)
    {
        return _dbContext.Find(id);
    }

    public SomeEntity GetReadonlyById(int id)
    {
        return _dbContext.SomeEntitities.AsNoTracking().SingleOrDefault(e => e.Id == id);
    }

    public SomeEntity Update(SomeEntity someEntity)
    {
        _dbContext.Update(someEntity);
        _dbContext.SaveChanges();
    }
}

public class SomeController
{
    private readonly SomeService _someService;

    //....

    [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        var someEntity = _someService.GetReadonlyById(id);
        if (someEntity == null)
        {
            return NotFound();
        }
        return someEntity;
    }

    [HttpPut("{id}")]
    public IActionResult Modify(int id, SomeEntity modified)
    {
        var someEntity = _someService.GetById(id);
        if (someEntity == null)
        {
            return NotFound();
        }
        someEntity.Someproperty = modified.Someproperty;
        _someService.Update(someEntity);
        return Ok(someEntity);
    }
}

Есть ли лучший способ сделать это?

Я также могу определить свой сервис следующим образом:

public class SomeService
{
    //...

    public SomeEntity GetById(int id)
    {
        return _dbContext.AsNoTracking.SingleOrDefault(e => e.Id == id);
    }

    public SomeEntity Update(int id, SomeEntity someEntity)
    {
        var entity = _dbContext.SomeEntities.Find(id);
        if (entity == null)
        {
            return null;
        }
        entity.Someproperty = someEntity.Someproperty;
        _dbContext.Update(entity);
        _dbContext.SaveChanges();
        return entity;
    }
}

public class SomeController
{
    private readonly SomeService _someService;

    //....

    [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        var someEntity = _someService.GetById(id);
        if (someEntity == null)
        {
            return NotFound();
        }
        return someEntity;
    }

    [HttpPut("{id}")]
    public IActionResult Modify(int id, SomeEntity modified)
    {
        var someEntity = _someService.Update(id, modified);
        if (someEntity == null)
        {
            return NotFound();
        }
        return Ok(someEntity);
    }
}

Какой способ лучше?

Ответы [ 2 ]

0 голосов
/ 13 августа 2019

Запросы на отслеживание бесполезны, если результаты используются в сценарии только для чтения. Они выполняются быстрее, поскольку нет необходимости настраивать информацию отслеживания изменений.

Вы можете поменять отдельный запрос, чтобы он не отслеживался:

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .AsNoTracking()
        .ToList();
}

Вы также можете изменить поведение отслеживания по умолчанию на уровне экземпляра контекста:

using (var context = new BloggingContext())
{
    context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

    var blogs = context.Blogs.ToList();
}

В идеале вы должны управлять инфраструктурой на уровне хранилища.

0 голосов
/ 21 мая 2018

В принципе, это более распространенная проблема.

Часто случается, что оптимизированные методы чтения не удобны для обновления сценариев, а удобные методы чтения для обновления сценариев имеют ненужные накладные расходы для чтения только сценариев.Я вижу 3 варианта:

  1. Игнорирование всех проблем с производительностью и просто используйте универсальный GetById из вашего первого подхода для чтения и обновления.Очевидно, что он применим для простых приложений и может не применяться для приложений с высокой нагрузкой.
  2. Использование CQRS .Это означает, что у вас будет совершенно отдельная модель данных для чтения и обновления.Поскольку операции чтения обычно не требуют сложной логики домена, это позволяет вам использовать любые оптимизации, такие как метод AsNoTracking, или даже использовать простой sql в репозиториях.Он применим для сложных приложений и требует больше кода.
  3. Попытка найти компромисс между этими двумя вариантами в соответствии с вашими конкретными потребностями.

Как отмечено в комментариях, ваш SomeService выглядиткак хранилище.В идеале доменная служба должна содержать только бизнес-логику и не должна смешивать ее с такими функциями инфраструктуры, как AsNoTracking.В то время как репозитории могут и должны содержать инфраструктурные функции, такие как AsNoTracking, Include и т. Д.

...