- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在 Entity Framework 6.1.3 中遇到与一对一关系相关的问题。
我有 2 个类(class)。
public class Package
{
public Guid Id { get; set; }
public string PackageNo { get; set; }
public double SendingCost{ get; set; }
public virtual PackageAppointment PackageAppointment { get; set; }
}
public class PackageAppointment
{
public DateTime Date { get; set; }
public virtual Package Package { get; set; }
}
PackageAppointment
的 map 类是:
public class PackageAppointmentMap
{
public PackageAppointmentMap()
{
Property(x => x.Date).IsRequired();
HasRequired(x => x.Package).WithOptional(x => x.PackageAppointment).Map(x => x.MapKey("PackageId"));
}
}
一切正常。我对这段关系没有任何问题。问题是查询数据库。每次我使用上下文查询数据库中的 Package
实体时,SQL Server 探查器都会生成类似这样的内容。
LINQ 查询:
var data = await Task.Run(() => GenericService.GetAll().Select(x => x.PackageNo));
SQL Server 探查器:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[PackageNo] AS [PackageNo],
[Extent1].[SendingCost] AS [SendingCost],
[Extent2].[Id] AS [Id1]
FROM
[dbo].[Package] AS [Extent1]
LEFT OUTER JOIN
[dbo].[PackageAppointment] AS [Extent2] ON [Extent1].[Id] = [Extent2].[PackageId]
我使用 context.Package...
进行的每个查询都没有从 PackageAppointment
(或任何其他一对一关系)中检索数据, Entity Framework 生成一个左外连接.
我项目中的实际情况是Package实体有5个一对一的关系。因此性能非常低。
也许我应该改变关系或其他什么。我真的不知道该怎么做才能解决这个性能问题。
请指教。
最佳答案
您可以将 Package 和 PackageAppointment 之间的关系更改为:
public PackageAppointmentMap()
{
Property(x => x.Date).IsRequired();
HasOptional(x => x.Package)
.WithOptionalPrincipal(x => x.PackageAppointment)
.Map(x => x.MapKey("PackageAppointmentId"));
}
这将使您的包表包含 FK PackageAppontmentId,并且您的查询将没有此连接。更改与 Package.HasRequired(x=>x.PackageAppointment) 的关系也将起作用(对于可能的原因,请参见下文)
访问包之后:
var query = dbContext.Packages.ToString();
返回:
SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[PackageNo] AS [PackageNo],
[Extent1].[SendingCost] AS [SendingCost],
[Extent1].[PackageAppointmentId] AS [PackageAppointmentId]
FROM [dbo].[Packages] AS [Extent1]
另一方面,访问 PackageAppointments:
var anotherQuery = dbContext.PackageAppointments.ToString();
将导致查询:
SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[Date] AS [Date],
[Extent2].[Id] AS [Id1]
FROM [dbo].[PackageAppointments] AS [Extent1]
LEFT OUTER JOIN [dbo].[Packages] AS [Extent2] ON ([Extent2].[PackageAppointmentId] IS NOT NULL) AND ([Extent1].[Id] = [Extent2].[PackageAppointmentId])
[编辑]
为什么会这样?
这看起来主要是为了更改跟踪而完成的。
场景:
你有一个 PackageAppointment
具有必需的 Package
.这意味着,你的 PackageAppointment
表有外键 PackageId
, 所以当你加载 PackageAppointment
,更改跟踪器包含有关 PackageAppointment
的所有信息跟踪实体的所有可能更改,并更改 PackageAppointment.Package
引用很容易跟踪 - 你比较 PackageAppointment.PackageId
在您加载的实体中,即使您没有真正从 Package
加载记录表,与 PackageAppointment
相关联(延迟加载 = 关闭)。
另一方面,如果您加载 Package
, 你有属性(property) PackageAppointment
您可以更改以引用另一个 PackageAppointment。但是要跟踪此更改,您必须以某种方式获得 PackageAppointment.Id
与此包相关联。自 Package
表没有从自身到 PackageAppointment
的外键表,您必须进行连接才能获得 PackageAppointment.Id
, 与此相关Package
.换句话说,如果您不执行此连接,则此实体的更改跟踪将无效,并且会使您加载引用 PackageAppointment
如果您对其进行任何更改,这可能是无效的。
要证明这一点,请尝试输入 .AsNoTracking()
对于此特定查询并检查返回的查询。
所以代码
var trackingQuery = dbContext.PackageAppointments.ToString();
Console.WriteLine("==========================");
Console.WriteLine("Query with Change Tracker enabled");
Console.WriteLine(trackingQuery);
Console.WriteLine("==========================");
Console.WriteLine("\n\n");
var noTrackingQuery = dbContext.PackageAppointments.AsNoTracking().ToString();
Console.WriteLine("==========================");
Console.WriteLine("Query with Change Tracker disabled");
Console.WriteLine(noTrackingQuery);
Console.WriteLine("==========================");
结果如下输出:
==========================
Query with Change Tracker enabled
SELECT
1 AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[Date] AS [Date],
[Extent2].[Id] AS [Id1]
FROM [dbo].[PackageAppointments] AS [Extent1]
LEFT OUTER JOIN [dbo].[Packages] AS [Extent2] ON ([Extent2].[PackageAppointmentId] IS NOT NULL) AND ([Extent1].[Id] = [Extent2].[PackageAppointmentId])
==========================
==========================
Query with Change Tracker disabled
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Date] AS [Date]
FROM [dbo].[PackageAppointments] AS [Extent1]
==========================
可以看到,LEFT OUTER JOIN在这里神奇地消失了,证明这与Change Tracking系统有关。
关于c# - Entity Framework 中的左外连接一对一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39415558/
我在使用一对一映射时遇到问题。我搜索了互联网并找到了许多解决方案,但没有一个令人满意。大多数示例都带有将父实例存储在子类中的开销。 我只想在具有外键约束关系的子类中使用父 ID,但不想在子类中保留任何
我有以下设置: Micronaut 3.x Java 15 我要更新的实体: @Setter @Getter @Entity @ToString @Table(name = "single_choic
我正在使用AVAudioPlayer制作MP3播放器。我有多种MP3声音,想一一播放。以下是我的应用程序的逻辑: ///// For playing 1st sound mp3Player = [[A
所以这就是问题所在。我有 2 个模型: 裁判级别和裁判 两个都有: class RefereeLevel(models.Model): level = models.PositiveSmall
我想将数组添加到列表或多维数组(不是一次全部...)。但是我真的不明白为什么这应该那么难。 可以说我有这个: string[] a = { "h", "b"}; string[] b
我有一个长度为 1000 的数字序列,我将其分成 100 个长度的序列。所以我最终得到了 901 个长度为 100 的序列。让前 900 个序列为 trainX。 trainY 是这些序列中的第 2
关键字:association 一对一映射(一个班级只有一个班主任) ?
所以,这是我第一次学习计算机语言。我选择了python和django。现在,我了解了 python 和 django 的许多基本概念。我可以使用 View 和所有其他内容创建新页面。但我仍然对这些关系
在一对一映射中,我编写了以下代码行。 @GenericGenerator(name = "generator", strategy = "foreign", parameters = @Paramet
我有两个如下所示的实体 @Data @EqualsAndHashCode(callSuper = true) @Entity @Table(name = "foo") @Audited @AuditO
我的问题很简单.. 假设有 2 个类..书籍和作者 假设一本书只能由一位作者撰写。 一个作家可以写很多本书。 假设作者有唯一的名字。 [两个作者不能同名] 现在..假设所有 hibernate\JPA
我正在尝试创建一个实体,如下所示 @Data public class Person { @Id private String id; @OneToMany(mapp
我有一个包含字段的Project表 ID PROJECT_BASELINE_ATTRIBUTES_ID (FK for table PROJECT_BASELINE_ATTR) 这个表有如下映射
我正在学习基本的 hibernate 教程。我正在尝试在 2 个表之间建立一对一的关系。当我尝试插入 Client 表时它起作用了,但是当我尝试做相反的事情时(插入 Facture 表)我得到了这个异
我已经在 hibernate 3 中使用注释完成了一对一映射,我有两张表“组”和“类别”。类别是预定义的。当用户选择类别和组时,CategoryId和goupid应该只插入组表中。 那么应该如何映射。
我使用Linux服务Fedora 4.14.33-51.37.amzn1.x86_64。我想使用 NAT 1 对 1。例如是否相同problem我的方案是:我的服务器有两个网络接口(interface
我正在尝试与实体 Revision 创建一对一、自引用、双向关系(哇),看起来像这个: /** * @Entity() * @Table(name="rev") */ class Revisio
我需要两个实体之间的链接,所以我使用一对一 @Entity @Table(name = "T_USER") public class User implements Serializable {
一对一: 一对一的关系极为一个数据仅对应一个数据,用下图的结构图可以帮助理解: 下面用代码实现一下,首先要创建工程项目如下: 接着,我们定义模型: 来到models.py文件,创建两
假设我有5列。 pd.DataFrame({ 'Column1': [1, 2, 3, 4, 5, 6, 7, 8, 9], 'Column2': [4, 3, 6, 8, 3, 4, 1, 4, 3
我是一名优秀的程序员,十分优秀!