[英]How to use AsNoTracking in a service layer
I usually use AsNoTracking when I'm not intending to write anything.当我不打算写任何东西时,我通常使用 AsNoTracking。 How should I handle this in my service layer where dbContext is hidden behind it?
我应该如何在 dbContext 隐藏在它后面的服务层中处理这个问题? (I treat EF core as repository because it is repository)
(我将 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);
}
}
Is there any better way to do this?有没有更好的方法来做到这一点?
I can also define my service as follows:我还可以如下定义我的服务:
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);
}
}
What is the better way?更好的方法是什么?
Basically, it is more common problem.基本上,这是更常见的问题。
It is often happens that optimized reading methods are not convenient for updating scenarios and convenient reading methods for updating scenarios have unnecessary overhead for reading only scenarios.经常出现优化的读取方式不方便更新场景,方便的读取方式更新场景对只读场景有不必要的开销。 I see 3 options here:
我在这里看到 3 个选项:
GetById
from your first approach for reads and updates.GetById
进行读取和更新。 Obviously, it is applicable for simple applications and may not be applicable for high-load applications.AsNoTracking
method or even use a plain sql
in repositories.AsNoTracking
方法,甚至在存储库中使用普通的sql
。 It is applicable for complex apps and requires more code. As noted in comments your SomeService
looks like repository.如评论中所述,您的
SomeService
看起来像存储库。 Ideally, domain service should contain only business logic and shouldn't mix it with infrastructure features like AsNoTracking
.理想情况下,域服务应该只包含业务逻辑,而不应该将其与
AsNoTracking
等基础设施功能混合。 Whereas repositories can and should contain infrastructure features like AsNoTracking
, Include
and etc.而存储库可以并且应该包含基础设施功能,如
AsNoTracking
、 Include
等。
No tracking queries are useful when the results are used in a read-only scenario.当结果用于只读方案时,没有跟踪查询是有用的。 They are quicker to execute because there is no need to setup change tracking information.
它们执行速度更快,因为无需设置更改跟踪信息。
You can swap an individual query to be no-tracking:您可以将单个查询交换为不跟踪:
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.AsNoTracking()
.ToList();
}
You can also change the default tracking behavior at the context instance level:您还可以在上下文实例级别更改默认跟踪行为:
using (var context = new BloggingContext())
{
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var blogs = context.Blogs.ToList();
}
Ideally, you should manage the infrastructure stuff in the repository level.理想情况下,您应该在存储库级别管理基础设施。
Here is my solution.这是我的解决方案。 It works.
有用。
BASE CLASS OF ALL SERVICES所有服务的基础 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();
}
}
USING IN CONTROLLER在 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.