我在asp.net mvc应用程序中有这个简单的Delete Get和Post方法
public ActionResult Delete(int ehrId, int id)
{
EHR ehr = ehrRepository.FindById(ehrId);
PhysicalTest test = ehr.PhysicalTests.Where(t => t.ID == id).Single();
return View(test);
}
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int ehrId, int id)
{
EHR ehr = ehrRepository.FindById(ehrId);
PhysicalTest test = ehr.PhysicalTests.Where(t => t.ID == id).Single();
ehr.PhysicalTests.Remove(test);
unitOfWork.Commit();
TempData["Success"] = "You have deleted the Physical Test Succesfully";
return RedirectToAction("Index");
}
问题是,当我尝试以这种方式删除子对象时,EF会抱怨
操作失败:无法更改关系,因为 一个或多个外键属性是不可为空的。当一个 改变了关系,相关的外键属性是 设置为空值。如果外键不支持空值, 必须定义新的关系,外键属性必须是 分配了另一个非空值,或者不相关的对象必须是 删除。
一个答案是使用PhysicalTest(子元素)存储库而不是EHRRepository ..但这似乎不是一个好的解决方案,因为我想强制执行始终通过父对象查询的安全性,以避免用户编辑/删除不属于他的物理测试。
我希望将我的存储库限制为只是聚合根。
继承我当前的SqlRepository通用实现....我愿意接受建议。
public class SqlRepository<T> : IRepository<T>
where T : class, IEntity {
internal SummumnetDB context;
internal DbSet<T> _objectSet;
public SqlRepository(SummumnetDB context)
{
this.context = context;
this._objectSet = context.Set<T>();
}
public IQueryable<T> Find(Expression<Func<T, bool>> predicate) {
return _objectSet.Where(predicate);
}
public void Add(T newEntity) {
_objectSet.Add(newEntity);
}
public void Remove(T entity) {
_objectSet.Remove(entity);
}
public IQueryable<T> FindAll()
{
return _objectSet;
}
public T FindById(int id)
{
return _objectSet.Single(o => o.ID == id);
}
}
答案 0 :(得分:0)
EHR
和PhysicalTest
表单聚合EHR
是PhysicalTest
的聚合根目录,因为如果没有EHR,PhyscialTest
就不能存在(您的例外情况表明FK在{ {1}}不能为null)。存储库应该存在于每个聚合根,它应该提供处理关系的特定方法。
是的,它不是通用的,因为具有不同配置和要求的实体的通用方法不起作用。
您的代码有什么问题?调用PhysicalTest
不会删除测试。它只会将其FK设置为null。要删除ehr.PhysicalTests.Remove(test)
,您必须真正致电test
。要允许直接删除,您必须使用identifying relation。