遵循N层架构,我在尝试更新实体时遇到了问题。在我的Controller中,如果我手动设置属性,则更新工作正常,如果我设置将ViewModel映射到实体的属性,则会生成异常" ...无法使用相同的键跟踪多个对象"。 我该如何解决这个问题?
这是我的UnitOfWork:
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; }
}
这是我的Generic Repository + CurrencyRepository:
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
internal CoreContext _context;
internal DbSet<T> _entities;
public GenericRepository(CoreContext context)
{
_context = context;
_entities = context.Set<T>();
}
public virtual void Update(T entityToUpdate)
{
_context.Entry(entityToUpdate).State = EntityState.Modified;
}
public IEnumerable<T> GetBy(Expression<Func<T, bool>> predicate)
{
IEnumerable<T> query = _entities.Where(predicate).AsEnumerable();
return query;
}
}
public interface IGenericRepository<T> where T : class
{
void Update(T entity);
IEnumerable<T> GetBy(Expression<Func<T, bool>> predicate);
}
public class CurrencyRepository : GenericRepository<Currency>, ICurrencyRepository
{
public CurrencyRepository(CoreContext context)
: base(context) {
}
}
这是我的服务:
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());
}
答案 0 :(得分:1)
它在您的情况下不起作用,因为您正在使用IMapper.Map
重载,它会创建currency
对象的新实例。由于您的GetCurrencyById
在成功获取后跟踪您的实体这一事实,您将最终得到异常,因为您将需要具有相同密钥的实例(一个已在DbContext中跟踪,另一个已创建映射器) )。
你可以做两件事来阻止它:
AsNoTracking()
方法使用IMapper.Map
重载,它包含currency
的目标和源实例:
_mapper.Map(currency,currencyToUpdate);