我正在尝试编写一个将由其他存储库使用的 GenericEFRepository。我有一个保存方法如下。
public virtual void Save(T entity) // where T : class, IEntity, new() And IEntity enforces long Id { get; set; }
{
var entry = _dbContext.Entry(entity);
if (entry.State != EntityState.Detached)
return; // context already knows about entity, don't do anything
if (entity.Id < 1)
{
_dbSet.Add(entity);
return;
}
var attachedEntity = _dbSet.Local.SingleOrDefault(e => e.Id == entity.Id);
if (attachedEntity != null)
_dbContext.Entry(attachedEntity).State = EntityState.Detached;
entry.State = EntityState.Modified;
}
您可以在以下代码的注释中找到问题
using (var uow = ObjectFactory.GetInstance<IUnitOfWork>()) // uow is implemented like EFUnitOfWork which gives the DbContext instance to repositories in GetRepository
{
var userRepo = uow.GetRepository<IUserRepository>();
var user = userRepo.Get(1);
user.Name += " Updated";
userRepo.Save(user);
uow.Save(); // OK only the Name of User is Updated
}
using (var uow = ObjectFactory.GetInstance<IUnitOfWork>())
{
var userRepo = uow.GetRepository<IUserRepository>();
var user = new User
{
Id = 1,
Name = "Brand New Name"
};
userRepo.Save(user);
uow.Save();
// NOT OK
// All fields (Name, Surname, BirthDate etc.) in User are updated
// which causes unassigned fields to be cleared on db
}
我能想到的唯一解决方案是通过存储库创建实体,存储userRepo.CreateEntity(id: 1)
库将返回一个附加到 DbContext 的实体。但这似乎很容易出错,任何开发人员仍然可以使用new
关键字创建实体。
您对这个特定问题有什么解决方案建议?
注意:我已经知道使用 GenericRepository 和 IEntity 接口的优缺点。所以,“不要使用 GenericRepository,不要使用 IEntity,不要在每个实体中放一个长 Id,不要做你想做的事情”评论将无济于事。