繁体   English   中英

使用EF4 CTP5中的POCO以多对一关系删除子实体

[英]Deleting a child entity in a many-to-one relationship using POCO in EF4 CTP5

简洁版本:

使用经典的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能够在没有配置/连接实体或执行事务脚本的情况下处理这个问题。

非常感谢任何帮助,如果您需要更多信息,请告诉我。

哦,祝大家新年快乐。 :-)

如果它是应用程序架构中的一个选项,您可以考虑在您的实体上启用动态代理。 这使上下文能够创建实体的子类,从而覆盖您的属性以跟踪更改。 在您的情况下,当对象丢失它的引用时,这将删除与您的对象相对应的行(假设您在上下文中调用SaveChanges())。

可以在启用动态代理时启用

  • 该课程是公开的,没有密封。
  • 该类具有公共或受保护的属性(在您的示例中特别是包含“订单行”的集合属性)。
  • 该类具有公共或受保护的无参数构造函数。

看看这个问题,你似乎满足了这些要求。

启用动态代理可以通过在上下文中设置属性来完成(也可以在Entity Framework设计器视图中完成):

this.ContextOptions.ProxyCreationEnabled = true;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM