C# 使用UnitOfWork存储库和带有AutoMapper的服务进行EFCore更新
遵循N层体系结构,我当前在尝试更新实体时遇到问题。在我的控制器中,如果我手动设置属性,则更新工作正常,如果我设置将ViewModel映射到实体的属性,则会生成异常“…无法使用同一关键点跟踪多个对象”。 我怎样才能解决这个问题 这是我的工作单元:C# 使用UnitOfWork存储库和带有AutoMapper的服务进行EFCore更新,c#,model-view-controller,entity-framework-core,ef-core-2.0,C#,Model View Controller,Entity Framework Core,Ef Core 2.0,遵循N层体系结构,我当前在尝试更新实体时遇到问题。在我的控制器中,如果我手动设置属性,则更新工作正常,如果我设置将ViewModel映射到实体的属性,则会生成异常“…无法使用同一关键点跟踪多个对象”。 我怎样才能解决这个问题 这是我的工作单元: public class UnitOfWork : IUnitOfWork { private readonly CoreContext _context; private IGenericRepository<Currency&g
public class UnitOfWork : IUnitOfWork
{
private readonly CoreContext _context;
private IGenericRepository<Currency> currencyRepository;
private static string DataConnectionString => new DatabaseConfiguration().GetDataConnectionString();
public UnitOfWork(CoreContext context)
{
var optionsBuilder = new DbContextOptionsBuilder<CoreContext>();
optionsBuilder.UseSqlServer(DataConnectionString);
_context = new CoreContext(optionsBuilder.Options);
}
public int Commit()
{
return _context.SaveChanges();
}
public async Task CommitAsync()
{
await _context.SaveChangesAsync();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public IGenericRepository<Currency> CurrencyRepository
{
get { return this.currencyRepository ?? (this.currencyRepository = new GenericRepository<Currency>(_context)); }
}
}
public interface IUnitOfWork : IDisposable
{
int Commit();
Task CommitAsync();
IGenericRepository<Currency> CurrencyRepository { get; }
}
最后,这是我的控制器:
public class CurrencyController : Controller
{
private readonly ICurrencyService _currencyService;
private readonly IMapper _mapper;
public CurrencyController(ICurrencyService currencyService, IMapper mapper)
: base()
{
_currencyService = currencyService;
_mapper = mapper;
}
[HttpPost]
public ActionResult UpdateCurrency([DataSourceRequest] DataSourceRequest dsRequest, CurrencyViewModel currency)
{
if (currency != null && ModelState.IsValid)
{
var currencyToUpdate = _currencyService.GetCurrencyById(currency.CurrencyId);
if (currencyToUpdate != null)
{
//UPDATE NOT WORKING
//currencyToUpdate = _mapper.Map<CurrencyViewModel, Currency>(currency);
//UPDATE WORKING
currencyToUpdate.Description = currency.Description;
currencyToUpdate.Code= currency.Code;
currencyToUpdate.Symbol = currency.Symbol;
_currencyService.UpdateCurrency(currencyToUpdate);
_currencyService.SaveChanges();
}
}
return Json(ModelState.ToDataSourceResult());
}
公共类CurrencyController:控制器
{
专用只读ICurrencyService\u currencyService;
专用只读IMapper\u映射器;
公共货币控制器(ICurrencyService货币服务,IMapper映射器)
:base()
{
_currencyService=currencyService;
_映射器=映射器;
}
[HttpPost]
public ActionResult UpdateCurrent([DataSourceRequest]DataSourceRequest dsRequest,CurrencyViewModel货币)
{
if(currency!=null&&ModelState.IsValid)
{
var currencyToUpdate=\u currencyService.GetCurrencyById(currency.CurrencyId);
if(currencyToUpdate!=null)
{
//更新不工作
//currencyToUpdate=\u mapper.Map(货币);
//更新工作
currencyToUpdate.Description=currency.Description;
currencyToUpdate.Code=currency.Code;
currencyToUpdate.Symbol=currency.Symbol;
_currencyService.UpdateCurrency(currencyToUpdate);
_currencyService.SaveChanges();
}
}
返回Json(ModelState.ToDataSourceResult());
}
它在您的情况下不起作用,因为您使用的是IMapper.Map
重载,它创建了currency
对象的新实例。由于GetCurrencyById
在成功获取后跟踪实体,您将遇到异常,因为您必须使用相同的键创建实例(一个已经在DbContext中跟踪,另一个是mapper创建的新的)
有两件事可以防止它:
AsNoTracking()
方法IMapper.Map
重载,该重载同时获取currency
的目标和源实例:
_mapper.Map(货币、货币更新)public class CurrencyService : ICurrencyService
{
private readonly IUnitOfWork _unitOfWork;
public void UpdateCurrency(Currency currency)
{
_unitOfWork.CurrencyRepository.Update(currency);
}
public Currency GetCurrencyById(int Id)
{
return _unitOfWork.CurrencyRepository.GetBy(x => x.CurrencyId == Id).Single();
}
public int SaveChanges()
{
return _unitOfWork.Commit();
}
}
public interface ICurrencyService
{
Currency GetCurrencyById(int Id);
void UpdateCurrency(Currency currency);
int SaveChanges();
}
public class CurrencyController : Controller
{
private readonly ICurrencyService _currencyService;
private readonly IMapper _mapper;
public CurrencyController(ICurrencyService currencyService, IMapper mapper)
: base()
{
_currencyService = currencyService;
_mapper = mapper;
}
[HttpPost]
public ActionResult UpdateCurrency([DataSourceRequest] DataSourceRequest dsRequest, CurrencyViewModel currency)
{
if (currency != null && ModelState.IsValid)
{
var currencyToUpdate = _currencyService.GetCurrencyById(currency.CurrencyId);
if (currencyToUpdate != null)
{
//UPDATE NOT WORKING
//currencyToUpdate = _mapper.Map<CurrencyViewModel, Currency>(currency);
//UPDATE WORKING
currencyToUpdate.Description = currency.Description;
currencyToUpdate.Code= currency.Code;
currencyToUpdate.Symbol = currency.Symbol;
_currencyService.UpdateCurrency(currencyToUpdate);
_currencyService.SaveChanges();
}
}
return Json(ModelState.ToDataSourceResult());
}