Я работаю над одной из моих архитектурных проектов, используя MVC5, EntityFramework, Unity, UnitOfWork и Generic Repository, также я не использовал AutoMapper или что-либо подобное AutoMapper.
Всякий раз, когда я выполняю обновление в первый раз, оно работает отлично, но во второй раз это выдает мне ошибку ниже.
Присоединение сущности типа EntityModel.tblCompanyMaster завершилось неудачно, поскольку другая сущность того же типа уже имеет такое же значение первичного ключа. Это может произойти при использовании метода «Присоединить» или установке состояния объекта на «Неизменено» или «Изменено», если какие-либо объекты в графе имеют конфликтующие значения ключей. Это может быть потому, что некоторые объекты являются новыми и еще не получили сгенерированные базой данных значения ключей. В этом случае используйте метод «Добавить» или «Состояние добавленной» сущности для отслеживания графика, а затем установите состояние не новых сущностей на «Неизмененные» или «Измененные», в зависимости от ситуации.
Ошибка происходит в методе обновления прямо здесь [_dbSet.Attach (entity)]
public virtual void UpdateEntity(TEntity entity, string[] NoUpdateProperty = null)
{
_dbSet.Attach(entity);
_dbContext.Entry<TEntity>(entity).State = EntityState.Modified;
.
.
}
Вот мой код:
1) Единство
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
//container.RegisterType<DbContext, dbTestCMSEntities>();
container.RegisterSingleton<IUnitOfWork, UnitOfWork>();
container.RegisterSingleton(typeof(IDbHelper<>), typeof(DbHelper<>));
container.RegisterSingleton<ICompanyMasterBL, tblCompanyMasterBL>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
2) Единица работы
public interface IUnitOfWork
{
dbTestCMSEntities dbContext { get; }
void Save();
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
public dbTestCMSEntities dbContext { get; }
private bool _disposed = false;
public UnitOfWork(dbTestCMSEntities context)
{
dbContext = context;
}
public void Save()
{
try
{
dbContext.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
}
protected virtual void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
dbContext.Dispose();
}
}
this._disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
3) Универсальный репозиторий
public interface IDbHelper<TEntity> where TEntity : class
{
bool Exists(object pkId);
TEntity GetFirst(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, dynamic>> order = null);
IEnumerable<TEntity> GetMany(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, string>> order = null);
IEnumerable<TEntity> GetPagedList(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, Int64>> _order, int currentPageIndex, out int Total);
void InsertEntity(TEntity entity);
void InsertEntity(List<TEntity> entity);
void UpdateEntity(TEntity entity, string[] NoUpdateProperty = null);
void UpdateEntity(List<TEntity> entity, string[] NoUpdateProperty = null);
void Delete(object id);
void Delete(TEntity entity);
void DeleteEntity(Expression<Func<TEntity, bool>> condition);
}
public class DbHelper<TEntity> : IDbHelper<TEntity> where TEntity : class
{
protected readonly dbTestCMSEntities _dbContext;
protected DbSet<TEntity> _dbSet;
public DbHelper(IUnitOfWork unitOfWork)
{
_dbContext = unitOfWork.dbContext;
_dbSet = _dbContext.Set<TEntity>();
}
public bool Exists(object pkId)
{
return _dbSet.Find(pkId) != null;
}
public TEntity GetFirst(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, dynamic>> order = null)
{
IQueryable<TEntity> lstResult = _dbSet.AsNoTracking().AsQueryable();
if (order != null)
lstResult = lstResult.AsNoTracking().OrderBy(order).AsQueryable();
if (condition != null)
lstResult = lstResult.AsNoTracking().Where(condition).AsQueryable();
TEntity entity = lstResult.AsNoTracking().FirstOrDefault();
return entity;
}
public virtual IEnumerable<TEntity> GetMany(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, string>> order = null)
{
IQueryable<TEntity> lstResult = _dbSet.AsNoTracking().AsQueryable();
if (condition != null)
lstResult = lstResult.AsNoTracking().Where(condition).AsQueryable();
if (order != null)
lstResult = lstResult.AsNoTracking().OrderBy(order).AsQueryable();
return lstResult;
}
public virtual IEnumerable<TEntity> GetPagedList(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, Int64>> _order, int currentPageIndex, out int Total)
{
IQueryable<TEntity> lstResult = _dbSet.AsNoTracking().AsQueryable();
if (condition != null)
lstResult = lstResult.AsNoTracking().Where(condition).AsQueryable();
Total = lstResult.Count();
lstResult = lstResult.AsNoTracking().OrderByDescending(_order).AsQueryable().Skip((currentPageIndex - 1) * StringUtility.ItemsPerPage).Take(StringUtility.ItemsPerPage);
return lstResult;
}
/// <summary>
/// Insert single record
/// </summary>
/// <param name="entity"></param>
public virtual void InsertEntity(TEntity entity)
{
_dbSet.Add(entity);
}
/// <summary>
/// Insert multiple records
/// </summary>
/// <param name="entity"></param>
public virtual void InsertEntity(List<TEntity> entity)
{
_dbSet.AddRange(entity);
}
/// <summary>
/// Update single entity
/// </summary>
/// <param name="entity"></param>
/// <param name="NoUpdateProperty"></param>
public virtual void UpdateEntity(TEntity entity, string[] NoUpdateProperty = null)
{
_dbSet.Attach(entity);
_dbContext.Entry<TEntity>(entity).State = EntityState.Modified;
if (NoUpdateProperty != null)
{
foreach (string item in NoUpdateProperty)
{
_dbContext.Entry<TEntity>(entity).Property(item).IsModified = false;
}
}
}
/// <summary>
/// Update multiple entity
/// </summary>
/// <param name="entity"></param>
/// <param name="NoUpdateProperty"></param>
public virtual void UpdateEntity(List<TEntity> entity, string[] NoUpdateProperty = null)
{
foreach (TEntity item in entity)
{
_dbSet.Attach(item);
_dbContext.Entry<TEntity>(item).State = EntityState.Modified;
if (NoUpdateProperty != null)
{
foreach (string item1 in NoUpdateProperty)
{
_dbContext.Entry<TEntity>(item).Property(item1).IsModified = false;
}
}
}
}
/// <summary>
/// Generic Delete method for the entities. Delete one record only.
/// </summary>
/// <param name="id"></param>
public virtual void Delete(object id)
{
TEntity entityToDelete = _dbSet.Find(id);
Delete(entityToDelete);
}
/// <summary>
/// Generic Delete method for the entities. Delete one record only.
/// </summary>
/// <param name="entityToDelete"></param>
public virtual void Delete(TEntity entity)
{
if (_dbContext.Entry(entity).State == EntityState.Detached)
{
_dbSet.Attach(entity);
}
_dbSet.Remove(entity);
}
/// <summary>
/// Delete one or many records based on given condition
/// </summary>
/// <param name="condition"></param>
public void DeleteEntity(Expression<Func<TEntity, bool>> condition)
{
_dbSet.RemoveRange(_dbSet.Where(condition));
}
}
Я пробовал много способов, но мне это не помогло, я думаю, что сделал что-то не так с Unity & Unit Of Work, но трудно идентифицировать. Спасибо заранее, чтобы помочь мне.