简短版:
使用经典的Order和OrderLine示例,如何在POCO中执行以下操作:
public partial class Order {
public void RemoveInvalidOrderLines() {
OrderLines.Remove(OrderLines.Where(ol => ol.Quantity > MaxQuantity));
}
}
在使用POCO的多对一关系中,这仅删除OrderLine中对Order的引用。有没有办法自动删除OrderLine实体?或者我是否必须注入存储库或将代码提升到服务中?在数据库中使用触发器?这有什么模式或最佳实践吗?我在网上找到的所有例子似乎都使用了一些简单的添加内容,“这就是你应该使用POCO的原因”: - )
情况:
在VS2010中使用EF4 CTP5,生成持久性无知的POCO(动态代理),我在如何处理相关“子”实体的删除方面遇到了困难。
问题: 下面的Employee类中的ICollection Relative中的Remove方法仅删除关系,而不删除最终实体。有没有办法强制它删除实体,而无需注入存储库/服务或从实体中提取代码?我想要一个干净的类似POCO的课程。
动机: 没有员工,相对实体不能存在,因此处理添加,删除等最自然的地方是在Employee类中。再说一遍,我愿意接受建议。 : - )
示例: 一个员工可以有很多亲戚。 Employee类有一个存储库,提供常用的查找程序。我希望Employee能够删除亲属,而不仅仅是FK关系。我是否必须注入存储库或类似物才能执行此操作?我试图将上下文和存储库保留在POCO之外。
假设以下表格:
Employee:
Id int (PK, not null)
Name varchar
Relative:
Id int (PK, not null)
EmployeeId int (FK, not null)
Name varchar
生成以下POCO:
public partial class Employee {
...
public virtual ICollection<Relative> Relatives
{
get
{
if (_relatives == null)
{
var newCollection = new FixupCollection<Relative>();
newCollection.CollectionChanged += FixupRelatives;
_relatives = newCollection;
}
return _relatives;
}
set
{
if (!ReferenceEquals(_relatives, value))
{
var previousValue = _relatives as FixupCollection<Relative>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupRelatives;
}
_relatives = value;
var newValue = value as FixupCollection<Relative>;
if (newValue != null)
{
newValue.CollectionChanged += FixupRelatives;
}
}
}
}
当然,
Relative:
public partial class Relative {
...
public virtual Employee Employee
{
get { return _employee; }
set
{
if (!ReferenceEquals(_employee, value))
{
var previousValue = _employee;
_employee = value;
FixupEmployee(previousValue);
}
}
}
private Employee _employee;
}
现在,人们可以这样做:
var employeeRepository = new EmployeeRepository(dbContext);
var employee = employeeRepository.Get(1234);
var relative = new Relative { Name = "Lars" };
employee.Relatives.Add(relative);
context.SaveChanges();
并将亲属添加到Relative表中,并引用该员工。
但是,如果我想在Employee-class中实现DeleteRelative方法:
public void DeleteRelative(string name) {
Relatives.Remove(Relatives.FirstOrDefault());
}
(假设亲戚存在的天真代码等)
我明白了:
System.InvalidOperationException: The operation failed:
The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
这是完全可以理解的,因为Relative的EmployeeId字段不能为null。
因此,除了将存储库/上下文注入实体之外,还有可能以任何方式解决这个问题(恕我直言,这种方式违背了POCO的目的)。
另一种选择是将它全部包装在服务或事务脚本中,但同样,我希望EF4能够在没有配置/连接实体或执行事务脚本的情况下处理这个问题。
非常感谢任何帮助,如果您需要更多信息,请告诉我。
噢,祝大家新年快乐。 : - )答案 0 :(得分:1)
如果它是应用程序架构中的一个选项,您可以考虑在您的实体上启用动态代理。这使上下文能够创建实体的子类,从而覆盖您的属性以跟踪更改。在您的情况下,当对象丢失它的引用时,这将删除与您的对象相对应的行(假设您在上下文中调用SaveChanges())。
时可以启用动态代理
看看你似乎满足这些要求的问题。
启用动态代理可以通过在上下文中设置属性来完成(也可以在Entity Framework设计器视图中完成):
this.ContextOptions.ProxyCreationEnabled = true;