2

现在我完全不明白持久性无知如何应用于实体框架。我使用实体框架设计了一个经典的存储库和工作单元。

现在,想象一个简单的客户端场景,我需要读取一些对象列表,然后保存其中一个。我的实体包含一些对象图,例如,Person 实体包含 Address 复杂属性,其中 Addrress 是另一个实体,也是一个 Hobby 对象列表,它也是另一个实体。我的客户:

var personList = PersonRepository.GetAll();
PersonRepository.Dispose(); // it will dispose EF's ObjectContext 
var person = personList[0];
person.Address.City = "...";
person.Hobby.Remove(person.Hobby.First());
PersonRepository.SaveChanges(person);

正如你所看到的,我已经保持了持久性无知逻辑,我仅限于使用 person 对象及其边界,但是,在现实世界中,上面的代码片段将倾向于失败,因为我已经处理了分离对象工作单位。

所以,我考虑过使用一些实体包装器和一些方法,比如 ManageGraph(object obj, ObjectState state),以便在内部字典中保留所有更改的关系的任何其他更改。但是,我不喜欢这个解决方案,它看起来太脏了,看起来像 anty 模式:

person.Name = "some name";
person.ManageGraph(AddressObject, state.Modified);
rather then
person.ManageGraph(AddressObject, state.Added);

但是……执着的无知在哪里?为什么我要强制使用坏技巧来获得正确的工作?持久性无知意味着我必须在没有任何其他东西的情况下处理简单对象,所以它会像下面这样:

person.SomeProperty = SomeValue
person.ComplexProperty.OtherProperty = otherValue
person.ListOfComplexProperty.Add(new entity);

当然,我知道,我不想要神奇的解决方案,它不存在,但是,是否有一些好的解决方案或建议可以获得最好的工作?

4

1 回答 1

1

你没有分离你的实体,你只是在处理上下文。这意味着您的实体不再被任何有效上下文“跟踪”。当您从新上下文调用 SaveChanges 方法时,操作失败并且您没有异常(这没关系,因为实体在内存中,但它根本没有被任何跟踪,对于新上下文,它不存在)。您应该在释放上下文之前分离实体,然后在退出方法时将其附加回新上下文。如果您正在使用 DbContext,也许您应该看看这篇文章

然而,坚持无知是一个指导方针。使用实际的语言,几乎是不可能达到的。你最好的朋友是存储库模式和工作单元。他们将通过实现抽象将您的业务代码与上下文分离,并将这种与持久性相关的内容“隐藏”到业务代码中。我建议您不要关心在业务代码中分离实体。如果您绝对需要它(?),也许您应该在存储库级别进行。从业务代码中管理上下文生命周期是一种不好的方法,您应该将此逻辑保留在您的 repo/UoW 层中。

希望这可以帮助,

于 2015-04-16T06:39:11.970 回答