繁体   English   中英

如何在服务层中使用 AsNoTracking

[英]How to use AsNoTracking in a service layer

当我不打算写任何东西时,我通常使用 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);
    }
}

更好的方法是什么?

基本上,这是更常见的问题。

经常出现优化的读取方式不方便更新场景,方便的读取方式更新场景对只读场景有不必要的开销。 我在这里看到 3 个选项:

  1. 忽略所有性能问题,只使用第一种方法中的通用GetById进行读取和更新。 显然,它适用于简单的应用,可能不适用于高负载的应用。
  2. 使用CQRS 这意味着您将拥有完全独立的数据 model 用于读取和更新。 由于读取通常不需要复杂的域逻辑,它允许您使用任何优化,如AsNoTracking方法,甚至在存储库中使用普通的sql 它适用于复杂的应用程序并且需要更多的代码。
  3. 尝试根据您的特定需求在这两个选项之间找到一些折衷方案。

如评论中所述,您的SomeService看起来像存储库。 理想情况下,域服务应该只包含业务逻辑,而不应该将其与AsNoTracking等基础设施功能混合。 而存储库可以并且应该包含基础设施功能,如AsNoTrackingInclude等。

当结果用于只读方案时,没有跟踪查询是有用的。 它们执行速度更快,因为无需设置更改跟踪信息。

您可以将单个查询交换为不跟踪:

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();
}

理想情况下,您应该在存储库级别管理基础设施。

这是我的解决方案。 有用。

所有服务的基础 CLASS

public class ServicesBase
            {
                protected AppDbContext dbcontext { get; }
      
                public ServicesBase(AppDbContext dbcontext)
                {
                    this.dbcontext = dbcontext;      
                }
        
                public void AsNoTracking()
                {
                    dbcontext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
                }
        
                public void SaveChanges()
                {
                    dbcontext.SaveChanges();
                }
        
            }

在 CONTROLLER 中使用

_masterService.AsNoTracking();
var master = _masterService.GetById(1);
master.WagePerSquareMeter = 21;
_masterService.SaveChanges(); 

//or dbcontext.SaveChanges(), both of them will ot affect the database.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM