更新实体而不知道主键

问题描述:

给定以下代码,如何在不知道其Id的情况下向实体的某个属性添加元素并从数据库中检索该元素?更新实体而不知道主键

public async Task BookInPersonVisitAsync(Guid propertyId, DateTime dateTime, CancellationToken token) 
    { 
     var entity = new OnBoardingProcessEntity{ ExternalId = propertyId }; 

     DbContext.OnBoardingProcesses.Attach(entity); 

     entity.OnBoardingProcessVisits.Add(new OnBoardingProcessVisitEntity 
     { 
      DateTime = dateTime, 
      Occurred = false 
     }); 

     await DbContext.SaveChangesAsync(token); 
    } 

ExternalId只是一个我们用于外部参考的guid。这不工作,因为它没有设置id,但没有击中数据库,我们不能拥有它。

如果您需要从另一个实体(entity)引用实体(referencedEntity),则必须使用实体框架,您必须知道referencedEntity
否则,您可以添加仅将实体设置referencedEntity添加为空。
要知道referencedEntity或者您知道Id或者您必须以某种方式(从数据库)检索它。

在SQL(DML)中,如果(且仅当)ExternalId是候选键noy可为空,则可以插入OnBoardingProcessVisit记录,但插入语句将包含内部查询。

OnBoardingProcessVisit.OnBoardingProcess_Id = (
    SELECT 
     Id 
    FROM 
     OnBoardingProcess 
    WHERE 
     ExternalId = @propertyId) 

编辑
没有办法生成与EF该查询。你可以看看外部组件(免费而不是免费的,例如EntityFramework Extended,但在这种情况下,我认为这没有帮助)。

在这种情况下,我可能会尝试使用标准实体框架功能(因此从ExternalId中检索OnBoardingProcess需要1次往返)。
然后,如果往返速度太慢,请直接在数据库上运行SQL查询。
关于性能(和数据库一致性),在OnBoardingProcess.ExternalId(每种情况下)都添加一个唯一索引。

另一个建议,如果你决定往返。 在您的代码中,entity将成为代理。如果您不禁用延迟加载,则使用代码时,您将访问财产 entity.OnBoardingProcessVisits(在语句entity.OnBoardingProcessVisits.Add中)时执行一次往返。
因此,在这种情况下,禁用延迟加载或使用不同的方式执行相同的操作。
你的情况不同的方式是一样的东西

var onBoardingProcessVisitEntity new OnBoardingProcessVisitEntity 
{ 
    DateTime = dateTime, 
    Occurred = false, 
    OnBoardingProcess = entity 
}); 

DbContext.OnBoardingProcessVisits.Add(onBoardingProcessVisitEntity); 
await DbContext.SaveChangesAsync(token); 
+0

感谢您对输入,问题是,我该如何让EF生成脚本就像在你的榜样?现在我可以在EF中说,外部ID是一个候选键。 – Marco

+0

请参阅答案中的编辑部分 – bubi

+0

看来我可以在最新版本的EF中使用HasAlternateKey :(感谢您的帮助。 – Marco