简体   繁体   English

使用实体框架(代码优先)将具有可空关联的实体更新/更改为null

[英]Using Entity Framework (Code First) to update/change an entity with a nullable association to null

I have an association (virtual, lazyloaded one-to-one-or-null) and I want to set it to null. 我有一个关联(虚拟的,延迟加载的一对一或空值),我想将其设置为null。 I've found that it's not possible unless you load this association first, and then set it to null. 我发现除非首先加载此关联, 然后将其设置为null, 否则这是不可能的。

someEntity.AnotherEntity.ToString(); // Needs to be done in order to force a load since im using a service that wraps a generic repository
someEntity.AnotherEntity = null; // Now this works because i loaded above.

I google around a lot and it seems that eager-loading someEntity is an option, or adding a new property to the SomeEntity that is: 我在Google上搜索了很多东西,似乎很想加载someEntity是一个选择,或者向SomeEntity添加一个新属性,即:

[ForeignKey("AnotherEntity")] // With this annotation
int? AnotherEntity_Id // Added this property

And then work with the nullable AnotherEntityId instead of the association property AnotherEntity . 然后使用可为null的AnotherEntityId代替关联属性AnotherEntity

I for now use the second approach, and it bloats the Entity a bit, but seem more solid because you also don't need the extra SQL calls. 我现在使用第二种方法,它使Entity有点膨胀,但看起来更加牢固,因为您也不需要额外的SQL调用。

  1. Why can't I set associations to null and have EF understand this? 为什么我不能将关联设置为null并让EF理解这一点?

  2. What about the second approach i'm using. 那我使用的第二种方法呢? Is it a good practice or is there something better? 这是一个好习惯还是有更好的选择?

1 Why can't I set associations to null and have EF understand this? 1为什么我不能将关联设置为null并使EF理解这一点?

It's because of the nature of your entity with lazy loading enabled. 这是因为您的实体的性质启用了延迟加载。 With lazy loading, the entity does not materialize in the property until you call the get method on the navigation property. 对于延迟加载,直到您在Navigation属性上调用get方法,该实体才会在该属性中实现。 If you call set , sure this can set a property's backing field to null, but EF will ignore it because it was null to begin with. 如果调用set ,请确保这可以将属性的后备字段设置为null,但是EF会忽略它,因为开始时它为null。 The property's backing field does not get populated until you call get unless you eager load. 除非您渴望加载,否则在调用get之前,不会填充该属性的后备字段。

2 What about the second approach i'm using. 2我使用的第二种方法呢? Is it a good practice or is there something better? 这是一个好习惯还是有更好的选择?

One easy workaround is to force lazy loading if you haven't already eager loaded, by doing this: 一个简单的解决方法是通过执行以下操作来强制延迟加载(如果尚未加载):

if (someEntity.AnotherEntity != null) // this will lazy load the instance
    someEntity.AnotherEntity = null; // now tell EF to remove the association

The statement in the if block will invoke the get method on the property and lazy load it if it hasn't already been eager loaded. if块中的语句将在属性上调用get方法,并在尚未急于加载时延迟加载它。 Now the EF context knows this entity is being tracked, so when you set it to null in the next line, EF will remember that you want to null it out when you go to save changes. 现在,EF上下文知道该实体已被跟踪,因此当您在下一行将其设置为null时,EF将记住您想在保存更改时将其清空。

Also, as you noted, if you are exposing a nullable foreign key property for the association, you can just set it. 另外,正如您指出的那样,如果要为关联公开可空的外键属性,则可以对其进行设置。 Since it is not virtual, changing it to null will also have the same effect of telling your EF context that you want to remove the association. 由于它不是虚拟的,因此将其更改为null也将具有与告诉EF上下文您要删除关联的效果相同的效果。

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

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