使用EF 4.1 Code First,我有一个会员实体,而 HomeAddress 又有两个“一对多”关系 strong>和 WorkAddress 。它还有一个布尔属性来声明是否使用这些地址中的任何一个。
我有两个我无法弄清楚的问题:
每当我更新成员的地址时,都会在MemberAddresses表中添加一条新记录(带有新的ID值),并且不会删除现有记录。虽然从前端角度来看它看起来很好,因为父成员表中的HomeAddressId和WorkAddressId用新记录更新,旧记录保存在表中(orhpaned)。我不希望它在更新地址时添加新的地址记录。我只希望它更新现有记录。如果它必须添加一个新的,那么我至少希望它清除旧的。
有时我想从表中删除地址记录。例如,如果成员以前有一个关联的HomeAddress,后来DontUseHomeAddress设置为true,我希望从表中删除该地址。到目前为止,我已经尝试将其设置为null,但这只是阻止任何更新。它不会删除它。
我确信只有一些我遗漏的代码片段,所以我在下面列出了我认为可能影响到的所有相关代码。
public abstract class Entity
{
public int Id { get; set; }
}
public class Member : Entity
{
public string Name { get; set; }
public bool DontUseHomeAddress { get; set; }
public virtual MemberAddress HomeAddress { get; set; }
public bool DontUseWorkAddress { get; set; }
public virtual MemberAddress WorkAddress { get; set; }
//... other properties here ...
}
public class MemberMap : EntityTypeConfiguration<Member>
{
public MemberMap()
{
ToTable("Members");
Property(m => m.Name).IsRequired().HasMaxLength(50);
//TODO: Somehow this is creating new records in the MemberAddress table instead of updating existing ones
HasOptional(m => m.HomeAddress).WithMany().Map(a => a.MapKey("HomeAddressId"));
HasOptional(m => m.WorkAddress).WithMany().Map(a => a.MapKey("WorkAddressId"));
}
}
public class MemberAddressMap : EntityTypeConfiguration<MemberAddress>
{
public MemberAddressMap()
{
ToTable("MemberAddresses");
Property(x => x.StreetAddress).IsRequired().HasMaxLength(255);
Property(x => x.City).IsRequired().HasMaxLength(50);
Property(x => x.State).IsRequired().HasMaxLength(2);
Property(x => x.ZipCode).IsRequired().HasMaxLength(5);
}
}
以下是我的控制器调用的我的存储库类中的 InsertOrUpdate 方法:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : Entity
{
private readonly EfDbContext _context;
private readonly DbSet<TEntity> _dbSet;
public Repository(EfDbContext context)
{
_context = context;
_dbSet = _context.Set<TEntity>();
}
public bool InsertOrUpdate(TEntity entity)
{
if(entity.Id == 0)
{
_dbSet.Add(entity);
}
else
{
_context.Entry(entity).State = EntityState.Modified;
}
_context.SaveChanges();
return true;
}
//... Other repository methods here ...
}
编辑:添加UnitOfWork和MemberServices的代码
public class MemberServices:IMemberServices { 私人只读IUnitOfWork _unitOfWork; private readonly IRepository _memberRepository;
public MemberServices(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_memberRepository = unitOfWork.RepositoryFor<Member>();
}
public Member Find(int id)
{
return _memberRepository.FindById(id);
}
public bool InsertOrUpdate(Member member)
{
// if(member.HomeAddress != null)
// _unitOfWork.SetContextState(member.HomeAddress, EntityState.Modified);
//
// if(member.WorkAddress != null)
// _unitOfWork.SetContextState(member.WorkAddress, EntityState.Modified);
//
// if(member.DontUseHomeAddress)
// {
// //TODO: This is an attempted hack... fix it by moving somewhere (possibly to repository)
// var context = new EfDbContext();
// context.Set<MemberAddress>().Remove(member.HomeAddress);
// context.SaveChanges();
// }
_memberRepository.InsertOrUpdate(member);
return true;
}
}
public class UnitOfWork : IUnitOfWork
{
private readonly EfDbContext _context;
public UnitOfWork()
{
_context = new EfDbContext();
}
public IRepository<T> RepositoryFor<T>() where T : Entity
{
return new Repository<T>(_context);
}
public void Attach(Entity entity)
{
_context.Entry(entity).State = EntityState.Unchanged;
}
public void SetContextState(Entity entity, EntityState state)
{
_context.Entry(entity).State = state;
}
public void Save()
{
_context.SaveChanges();
}
}
答案 0 :(得分:2)
设置状态_context.Entry(entity).State = EntityState.Modified;
不会影响相关实体的状态。如果您想要处理相关实体的更改,您还必须将其状态设置为Modified
:
if (member.HomeAddress != null)
_context.Entry(member.HomeAddress).State = EntityState.Modified;
if (member.WorkAddress != null)
_context.Entry(member.WorkAddress).State = EntityState.Modified;
_context.Entry(member).State = EntityState.Modified;
这不再是通用的了。
要删除实体,您必须调用适当的方法来删除实体;将导航属性设置为null
是不够的:
_context.MemberAddresses.Remove(member.HomeAddress);