我们正在使用实体框架代码优先与外键关系。 我们调查对来自于我们的应用程序中的实体的ICollection处理删除对象的方式。
当我们与孩子关系的实体,我们可以直接添加对象使用Add方法的ICollection的。 现在,当您使用删除你的错误
System.InvalidOperationException发生消息=操作失败:关系不能被改变,因为一个或多个外键的属性是不可为空。 当一个变化是有关系作出的相关外键属性设置为空值。 如果外键不支持空值,新的关系必须定义,外键属性必须指定一个非空值,或者无关的对象必须被删除。
我理解,这是因为在集合中删除仅删除由归零外键关系。 我们想写我们的业务逻辑在我们的实体,并允许拆除。
因此,获得根实体搞出来的是Repostiory如顺序OrderRepository然后调用实体的一些具体方法如Order.AddOrderline(Orderline orderline)
这增加的订单行的订单virtual ICollection<OrderLine> OrderLines
然而,我们不能写这样的代码Order.CancelOrderline(int orderLineId)
因为简单地从ICollection中移除导致储蓄变动的错误。
似乎没有成为无论如何仅通过操纵对象的集合来实现这一目标。 很显然,我们可以从上下文直接删除。 不过,我想使它成为实体的一部分。 我们可以清理某些实体与实体框架的SaveChanges事件没有外键? 显然需要告诉EF他们是否有空外键可以删除哪些实体。
目前,我们正在使用的存储库模式,使控制器不访问上下文。 我能明显使用订单行库或订单信息库中删除OrderLine的方法。 然而只是想知道如果有可能写在实体的代码不会对持久性机制的引用。
思考? 我们要这一切错了吗? 难道其他的ORM允许您刚刚从子集合删除?
我不知道下面是你的解决方案,但实体框架支持确定关系 。 在这种关系中子实体(相关)到父(委托人)的外键必须是儿童实体的(复合)主键的一部分。 例如-用DbContext
数据注解-你的模型类必须是这样的:
public class Order
{
[Key]
public int OrderId { get; set; }
public ICollection<OrderLine> OrderLines { get; set; }
}
public class OrderLine
{
[Key, ForeignKey("Order"), Column(Order = 1)]
public int OrderId { get; set; }
[Key, Column(Order = 2)]
public int OrderLineId { get; set; }
public Order Order { get; set; }
}
您可以使OrderLineId
如果你想要一个自动生成的身份。 重要的是唯一的FK到Order
的是PK的一部分。
一个这样的代码,例如...
using (var ctx = new MyContext())
{
var order = ctx.Orders.Include("OrderLines").Single(o => o.OrderId == 1);
var orderLineToDelete = order.OrderLines
.FirstOrDefault(ol => ol.OrderLineId == 5);
if (orderLineToDelete != null)
order.OrderLines.Remove(orderLineToDelete);
ctx.SaveChanges();
}
......的确会删除 orderLineToDelete
从数据库中。
更多详细信息, 这里的部分“ 识别和非识别关系的思考 ”。
正如你发现,你只是一个集合的实体徘徊附加到对象上下文中移除一个实体,给你,当你调用一个错误SaveChanges()
; 我用域事件,使从通过信息库对象上下文移除实体的整洁方式。
我在我的答复中详述这种方法对这一问题 。
文章来源: Is it possible to remove child from collection and resolve issues on SaveChanges?