gpt4 book ai didi

c# - 在 Entity Framework 中保存实体的通用方法

转载 作者:行者123 更新时间:2023-11-30 19:43:37 24 4
gpt4 key购买 nike

我正在尝试编写一个将由其他存储库使用的 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 接口(interface)的利弊。所以,“不要使用 GenericRepository,不要使用 IEntity,不要在每个 Entity 中放置一个长 Id,不要做你想做的事”评论不会有帮助。

最佳答案

是的,它很容易出错,但这就是 EF 和存储库的问题。您必须在设置要更新的任何数据(在您的情况下为 Name )之前创建实体并附加它,或者必须为要保留的每个属性而不是整个实体设置修改后的状态(因为您可以想象开发人员会忘记这样做)。

第一个解决方案导致在您的存储库上执行此操作的特殊方法:

public T Create(long id) {
T entity = _dbContext.Set<T>().Create();
entity.Id = id;
_dbContext.Set<T>().Attach(entity);
return entity;
}

第二个解决方案需要类似的东西

public void Save(T entity, params Expression<Func<T, TProperty>>[] properties) {

...

_dbContext.Set<T>().Attach(entity);
if (properties.Length > 0) {
foreach (var propertyAccessor in properties) {
_dbContext.Entry(entity).Property(propertyAccessor).IsModified = true;
}
} else {
_dbContext.Entry(entity).State = EntityState.Modified;
}
}

你会这样调用它:

userRepository(user, u => u.Name);

关于c# - 在 Entity Framework 中保存实体的通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14427113/

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