让我的 Entity Framework 代码更高效
Make My Entity Framework Code more Efficient
我们有一个 Repository
class。虽然这个 class 有一些自定义行为,但它包装了一个标准 ObjectContext
对象,因此它主要是标准 Entity Framework.
目前,我们有以下代码块,它可以工作但执行起来很糟糕。 (target
是一个 CostingLineItem
。代码更改了此 CostingLineItem
的 AddedByEmployee
引用。)
if (target.AddedByEmployee != null)
target.AddedByEmployee.CostingLineItems.Remove(target);
byEmployee.CostingLineItems.Add(target);
target.AddedByEmployee = byEmployee;
因为我们启用了延迟加载,这段代码同时加载了 target.AddedByEmployee.CostingLineItems
和 byEmployee.CostingLineItems
集合,它们可能有数千行。
很遗憾,我无法更改此代码的延迟加载设置。我需要找到一种提高效率的方法,但似乎对我没有任何作用。
这是我到目前为止尝试过的方法。
方法一:
target.AddedByEmployeeId = byEmployee.Id;
没有效果。 AddedByEmployeeId
列仍然包含原始值。显然,最初的员工推荐信仍然存在并且优先。
方法二:
target.AddedByEmployee = byEmployee;
抛出以下异常。同样,最初的员工推荐信似乎仍然存在。
Multiplicity constraint violated. The role 'Employees' of the relationship 'Leo.Domain.FK_CostingLineItem_Employees' has multiplicity 1 or 0..1.
方法三:
Repository.Detach(target.AddedByEmployee);
target.AddedByEmployee = byEmployee;
Detach()
(依次调用 ObjectContext.Detach()
)抛出以下异常:
The object cannot be detached because it is not attached to the ObjectStateManager.
方法四:
target.AddedByEmployee.CostingLineItems.Remove(target);
target.AddedByEmployee = byEmployee;
这有效!但它仍在加载 target.AddedByEmployee.CostingLineItems
,我想避免这种情况。
我意识到我没有在这里展示我们所有的代码(这是不可能的)。但是代码在下面使用了标准 ObjectContext
。我真正想要的是对 Entity Framework 有一些见解并且可以就我可以尝试的其他内容或我可以检查的其他内容提供一些想法的人。
注意:我们目前是 运行 Visual Studio 2012。我会看看我们是否可以更新到 2015。我很想知道自我们的版本以来是否有任何变化正在使用它可以使上面的一些方法在以前没有的地方工作。
您是否尝试过直接从 DbSet<>
中删除目标,而不是从附加的 CostingLineItems
中删除它。
context.Set<CostingLineItems>().Remove(target)
这应该在不加载集合的情况下删除目标。
经过广泛的研究和测试,我想我确定了我的问题所在。
问题是有问题的实体刚刚被克隆到数据库中。克隆代码遵循一系列规则,这些规则规定相关项是否也被克隆或仅引用被克隆。
无论如何,AddedByEmployee
已经设置好了。因此尝试第二次设置它,或者只是尝试设置 ID 会因为与已经设置的冲突而出现问题。
我们有一个 Repository
class。虽然这个 class 有一些自定义行为,但它包装了一个标准 ObjectContext
对象,因此它主要是标准 Entity Framework.
目前,我们有以下代码块,它可以工作但执行起来很糟糕。 (target
是一个 CostingLineItem
。代码更改了此 CostingLineItem
的 AddedByEmployee
引用。)
if (target.AddedByEmployee != null)
target.AddedByEmployee.CostingLineItems.Remove(target);
byEmployee.CostingLineItems.Add(target);
target.AddedByEmployee = byEmployee;
因为我们启用了延迟加载,这段代码同时加载了 target.AddedByEmployee.CostingLineItems
和 byEmployee.CostingLineItems
集合,它们可能有数千行。
很遗憾,我无法更改此代码的延迟加载设置。我需要找到一种提高效率的方法,但似乎对我没有任何作用。
这是我到目前为止尝试过的方法。
方法一:
target.AddedByEmployeeId = byEmployee.Id;
没有效果。 AddedByEmployeeId
列仍然包含原始值。显然,最初的员工推荐信仍然存在并且优先。
方法二:
target.AddedByEmployee = byEmployee;
抛出以下异常。同样,最初的员工推荐信似乎仍然存在。
Multiplicity constraint violated. The role 'Employees' of the relationship 'Leo.Domain.FK_CostingLineItem_Employees' has multiplicity 1 or 0..1.
方法三:
Repository.Detach(target.AddedByEmployee);
target.AddedByEmployee = byEmployee;
Detach()
(依次调用 ObjectContext.Detach()
)抛出以下异常:
The object cannot be detached because it is not attached to the ObjectStateManager.
方法四:
target.AddedByEmployee.CostingLineItems.Remove(target);
target.AddedByEmployee = byEmployee;
这有效!但它仍在加载 target.AddedByEmployee.CostingLineItems
,我想避免这种情况。
我意识到我没有在这里展示我们所有的代码(这是不可能的)。但是代码在下面使用了标准 ObjectContext
。我真正想要的是对 Entity Framework 有一些见解并且可以就我可以尝试的其他内容或我可以检查的其他内容提供一些想法的人。
注意:我们目前是 运行 Visual Studio 2012。我会看看我们是否可以更新到 2015。我很想知道自我们的版本以来是否有任何变化正在使用它可以使上面的一些方法在以前没有的地方工作。
您是否尝试过直接从 DbSet<>
中删除目标,而不是从附加的 CostingLineItems
中删除它。
context.Set<CostingLineItems>().Remove(target)
这应该在不加载集合的情况下删除目标。
经过广泛的研究和测试,我想我确定了我的问题所在。
问题是有问题的实体刚刚被克隆到数据库中。克隆代码遵循一系列规则,这些规则规定相关项是否也被克隆或仅引用被克隆。
无论如何,AddedByEmployee
已经设置好了。因此尝试第二次设置它,或者只是尝试设置 ID 会因为与已经设置的冲突而出现问题。