【发布时间】:2018-09-17 16:56:13
【问题描述】:
我有一个带有链接类的类,例如想象一个带狗的人。它在 PersonDto 中是这样映射的:
public int? DogId { get; set; }
public virtual DogDto Dog { get; set; }
对于许多人来说,DogId 为空,但在我更改 Person 中的某些内容并执行 SaveChanges 之后,实体框架坚持认为它应该插入一个空白条目。
我的场景要大得多,但经过简化后可能如下所示:
var person = await _entities.Persons.Where(p => p.Name == "Ann")
.Select(p => p).Include(p => p.Dog).First();
person.Name = "Bob";
_entities.SaveChanges();
现在假设 Ann 没有狗,DogId 应该保持为空。
SQL Entity Framework Core 执行如下 INSERT:
DECLARE @inserted0 TABLE ([Id] int, [_Position] [int]);
MERGE [Dogs] USING (
VALUES (@p0, @p1, @p2, @p3, @p4, 0),
(@p5, @p6, @p7, @p8, @p9, 1)) AS i ([Col1], [Col2], [Col3], [Col4], [Col5],
_Position) ON 1=0
WHEN NOT MATCHED THEN
INSERT ([Col1], [Col2], [Col3], [Col4], [Col5])
VALUES (i.[Col1], i.[Col2], i.[Col3], i.[Col4], i.[Col5])
OUTPUT INSERTED.[Id], i._Position
INTO @inserted0;
我错过了什么。不会int吗?足以让它为空吗?
【问题讨论】:
-
为什么选择时要包括一只狗?如果您只需要更改人名!
-
我要试一试(我可能是错的),并说问题可能源于试图急切加载 (.Include(...)) 标记的导航属性作为虚拟,这意味着它是延迟加载的。你必须选择一个。而且由于默认情况下不启用延迟加载(因为它会导致像这样奇怪的副作用),除非您选择了延迟加载,否则您不应该使用 virtual 关键字。
-
您是否使用Lazy loading proxies,即代码中某处有
.UseLazyLoadingProxies()配置调用?因为如果这样做,您将无法从导航属性中删除virtual。您的“简化示例”也可以重现该问题吗?因为如果是,那就是 EF Core 错误。 -
我支持@IvanStoev,因为如果不使用延迟加载,
virtual关键字应该 无效。我几乎可以肯定我已经看到了文档中所写的内容。但由于删除 virtual 关键字解决了问题,因此可能存在疏忽。 -
我在 EF 团队工作,我猜不出会发生什么。我不希望虚拟与它有任何关系。但目前还不清楚症状是什么,或者您是否有任何其他配置,例如拥有的实体。可以同时使用急切加载和延迟加载。我想确保它不是错误,但要进行调查,我们需要一个能够重现该行为的项目。如果你能提供,请在GitHub.com/AspNet/EntityframeworkCore/issues/new 创建一个问题。您可以在问题中引用此线程。
标签: c# entity-framework entity-framework-core