gpt4 book ai didi

c# - 无法跟踪实体类型的实例,因为正在跟踪具有键值的另一个实例

转载 作者:行者123 更新时间:2023-12-04 12:58:18 25 4
gpt4 key购买 nike

我基本上是在尝试使用 EntityFrameWork 核心和 .Net 核心 3.1 来实现 CRUD。我的更新操作有问题,我无法使用修改后的值更新上下文。
我正在使用 postman 发起请求。
正如您在下面的代码中看到的那样,我正在尝试检查该客户是否存在以及它是否确实将修改后的对象传递给了上下文。
enter image description here
功能码

   [FunctionName("EditCustomer")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous,"post", Route = "update-customer")] HttpRequest req)
{
var customer = JsonConvert.DeserializeObject<CustomerViewModel>(new StreamReader(req.Body).ReadToEnd());
await _repo.UpdateCustomer(customer);
return new OkResult();
}
存储库方法
  public async Task UpdateCustomer(CustomerViewModel customerViewModel)
{
if (customerViewModel.CustomerId != null)
{
var customer = _context.Customers.Where(c => c.CustomerId.Equals(customerViewModel.CustomerId)).FirstOrDefault();

if (customer == null)
{
throw new Exception("customer not found");
}
else
{
_context.Customers.Update(_mapper.Map<Customers>(customerViewModel));
await _context.SaveChangesAsync();

}
}

}
映射
   public class CustomerManagerProfile : Profile
{
public CustomerManagerProfile()
{
CreateMap<CustomerDetails, CustomerDetailsViewModel>().ReverseMap();
CreateMap<CustomerOrders, CustomerOrdersViewModel>().ReverseMap();
CreateMap<CustomerOrderDetails, OrderDetailsViewModel>().ReverseMap();
CreateMap<Customers, CustomerViewModel>().ReverseMap();
}
}
解决方案
public async Task UpdateCustomer(CustomerViewModel customerViewModel)
{
if (customerViewModel.CustomerId != null)
{
var customer = _context.Customers.Where(c => c.CustomerId.Equals(customerViewModel.CustomerId)).FirstOrDefault();

if (customer == null)
{
throw new Exception("customer not found");
}
else
{
var customerModel = _mapper.Map<Customers>(customerViewModel);
_context.Entry<Customers>(customer).State = EntityState.Detached;
_context.Entry<Customers>(customerModel).State = EntityState.Modified;
await _context.SaveChangesAsync();

}
}

最佳答案

您可以做的最简单的调整是避免跟踪您的 Customers像这样检索:

var customer = _context
.Customers
.AsNoTracking() // This method tells EF not to track results of the query.
.Where(c => c.CustomerId.Equals(customerViewModel.CustomerId))
.FirstOrDefault();
从代码中并不完全清楚,但我的猜测是您的映射器返回了 Customer 的新实例。具有相同的 ID,这会混淆 EF。如果您要修改相同的实例,请调用 .Update()也应该工作:
var customer = _context.Customers.Where(c => c.CustomerId.Equals(customerViewModel.CustomerId)).FirstOrDefault();
customer.Name = "UpdatedName"; // An example.
_context.Customers.Update(customer);
await _context.SaveChangesAsync();
事实上,如果您跟踪您的 Customer你甚至不需要明确调用 .Update()方法,跟踪的目的是了解对实体进行了哪些更改并应将其保存到数据库中。因此,这也将起作用:
// Customer is being tracked by default.
var customer = _context.Customers.Where(c => c.CustomerId.Equals(customerViewModel.CustomerId)).FirstOrDefault();
customer.Name = "UpdatedName"; // An example.
await _context.SaveChangesAsync();

编辑:
您自己提供的解决方案首先跟踪您的查询( Customer )实例的结果,然后在写入数据库之前停止跟踪它(也称为分离),而是开始跟踪代表更新的 Customer 的实例。并将其标记为已修改。显然这也有效,但只是一种效率较低且优雅的方式。
事实上,如果你使用这种奇怪的方法,我看不到获取你的 Customer 的原因。根本。你当然可以:
if (!(await _context.Customers.AnyAsync(c => c.CustomerId == customerViewModel.CustomerId)))
{
throw new Exception("customer not found");
}

var customerModel = _mapper.Map<Customers>(customerViewModel);
_context.Customers.Update(customerModel);
await _context.SaveChangesAsync();

关于c# - 无法跟踪实体类型的实例,因为正在跟踪具有键值的另一个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62934010/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com