Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架-更新的关系不会检索从旧关系创建的数据_C#_Entity Framework_Sqlite_Ef Code First - Fatal编程技术网

C# 实体框架-更新的关系不会检索从旧关系创建的数据

C# 实体框架-更新的关系不会检索从旧关系创建的数据,c#,entity-framework,sqlite,ef-code-first,C#,Entity Framework,Sqlite,Ef Code First,我最近更新了我的实体框架(版本6.2.0)映射,以提高应用程序的性能,但不修改数据库架构。基本上,我有一对多的关系,我变成了一对一的关系 当我使用这个新映射创建新对象时,一切都按预期进行:对象以外键列中的正确值保存在数据库中,等等。当我重新启动应用程序(并重置DbContext)并访问这些对象时,实体的导航属性就实现了 当我尝试访问在此EF映射更新之前创建的对象时,就会出现问题。对于这些旧对象,导航属性为null,我无法访问关系的另一端 具体来说,我有两个定义如下的表: ______

我最近更新了我的
实体框架
(版本6.2.0)映射,以提高应用程序的性能,但不修改数据库架构。基本上,我有一对多的关系,我变成了一对一的关系

当我使用这个新映射创建新对象时,一切都按预期进行:对象以外键列中的正确值保存在数据库中,等等。当我重新启动应用程序(并重置DbContext)并访问这些对象时,实体的导航属性就实现了

当我尝试访问在此EF映射更新之前创建的对象时,就会出现问题。对于这些旧对象,导航属性为null,我无法访问关系的另一端


具体来说,我有两个定义如下的表:

 ______           _____________
|Sample|         |Sample_Result|
|------|         |-------------|
|Id    |<--------|Result_Of    |
|______|  Fk     |_____________|

SELECT *
  FROM Sample s
  INNER JOIN Sample_Result sr ON s.Id = sr.Result_Of;
Sample
SampleID (PK)

SampleResult
SampleResultID (PK)
SampleID (FK)
在我的dbContext中,我添加了以下映射:

 modelBuilder.Entity<SampleResultEntity>()
            .HasRequired(sr => sr.ResultOf)
            .WithRequiredDependent(s => s.Result);
我不会“丢失”行(如果我有40个样本,我会得到40行)。所以外键设置得很好


有人能解释一下这种行为吗?

您可能需要概述完整的表结构,因为根据您所描述的内容,您不能简单地根据模式将映射从1到多更改为1到1

一对多模式将如下所示:

 ______           _____________
|Sample|         |Sample_Result|
|------|         |-------------|
|Id    |<--------|Result_Of    |
|______|  Fk     |_____________|

SELECT *
  FROM Sample s
  INNER JOIN Sample_Result sr ON s.Id = sr.Result_Of;
Sample
SampleID (PK)

SampleResult
SampleResultID (PK)
SampleID (FK)
一对一架构将如下所示: 样品 样本ID(PK)

因此,在一个有效地包含1到1行的1对多模式中,SampleID=1,SampleResult的SampleResultID=16,SampleID=1。 如果您只是将映射更改为1对1,EF将期望两个表上的PK相等。由于SampleResult的主键是SampleResultId,因此不可能获得正确的记录,因为它将比较Sample.SampleId/w SampleResult.SampleResultId(不是SampleResult.SampleId)

您的新测试记录似乎有效,因为您可能会发现:

Sample.SampleID = **220**

SampleResult.SampleResultID = **220**
SampleResult.SampleID = 220
如果您对键使用标识(Int)列,那么这个问题的表现会有所不同,您可能会得到空链接,或者得到指向错误结果的链接。因为您使用的是guid,并且每个ID都是相对唯一的,所以结果将是空链接

我建议在测试数据库上使用探查器来捕获加载样本/结果对时使用的SQL,以验证是否加入了正确的列

在不更改模式的情况下,只要将SampleResult.SampleResultId设置为标识/默认值,并且您可以保证没有1对多实例(单个样本上的多个结果),您就应该能够更新EF中的映射,以将SampleResult上的SampleId视为键。这样,通过新映射,EF将2链接在一起。这意味着您以前的“新”测试记录将不再有效,因为它们将Sample.SampleID与SampleResult.SampleResultID相结合,但您的原始记录应该有效,新记录也应该有效。EF的键不必与表上的PK匹配,只要您首先使用DB(无迁移),并且满足模式。如果samplesultid的DB列默认为
NewSequentialId()
NewId()。如果PK是在代码中设置的,那么您可能需要将属性映射为常规列,并记下如何使用SampleId。如果您有任何其他实体基于SamplesUltId链接到SamplesUltd,则会“中断”。EF将在加入时将SampleId视为密钥


最后一点注意:我有点担心这样一个结论,即Sample和SampleResult之间的一对多关系会导致性能问题,这些问题可以通过重新映射到一对一来解决。虽然一对多的关系只包含一个子元素有点误导,但最终EF将在这两种情况下使用内部联接。我强烈怀疑还有别的事情在起作用。如果对新行使用
NewId()
/
GUID.New
,随着系统的增长,GUID键可能会出现问题。这是因为聚集索引中128位键的相对随机性会导致索引表中出现大量碎片。最好使用
NewSequentialId()
NewSequentialId()
的基于代码的实现来生成唯一但可排序的GUID,以最大限度地减少这种影响,并将其与数据库表上的定期索引维护相结合。

听起来您的数据库架构好像是被更改了。