![](/img/trans.png)
[英]Can I use EF Core 2.0 'AsNoTracking' in CRUD service GetAll?
[英]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 个选项:
GetById
进行读取和更新。 显然,它适用于简单的应用,可能不适用于高负载的应用。AsNoTracking
方法,甚至在存储库中使用普通的sql
。 它适用于复杂的应用程序并且需要更多的代码。 如评论中所述,您的SomeService
看起来像存储库。 理想情况下,域服务应该只包含业务逻辑,而不应该将其与AsNoTracking
等基础设施功能混合。 而存储库可以并且应该包含基础设施功能,如AsNoTracking
、 Include
等。
当结果用于只读方案时,没有跟踪查询是有用的。 它们执行速度更快,因为无需设置更改跟踪信息。
您可以将单个查询交换为不跟踪:
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.