在Entity Framework 6中,虚拟属性不会惰性加载(带有警告)

3

I'm stuck...

Here's my model:

public class Payment 
{
    [ForeignKey("RecipientId")]
    public virtual Account Recipient { get; set; }

    public string RecipientId { get; set; } 

    [Key, Column(TypeName = "char"), MaxLength(36)]
    public string PaymentId { get; set; }
}

这个模型可以通过流畅的API表示为以下内容:

modelBuilder.Entity<Payment>()
    .HasRequired(t => t.Recipient)
    .WithMany()
    .HasForeignKey(t => t.RecipientId)
    .WillCascadeOnDelete(false);

这个方案已经使用了近3年,我们在这个映射上从未发现过问题。

最近,我们决定将"MaxLength"属性更改为您在上面看到的内容。它从"8"变成了"36"。

我们之前的ID开始发生冲突,因此是时候改变了。

代码中的所有更改都很好。我们的单元测试全部通过。当我们在本地运行项目时,我们看到了正确的结果。

推向生产环境也相当正常。我们修改了我们的表,并调整了我们的索引以反映新的列类型长度(从MaxLength(8)变为MaxLength(36))。

同样......这是我们在本地执行的相同步骤。

问题来了:

使用新的、更长的"PaymentId"创建和保存的实体(Payment)没有出现错误。添加关系似乎也可以正常工作。

当我们执行任何一个查询API(Find、ToList、SingleOrDefault等...)时出现了错误。

我们的惰性加载不起作用。收件人处于空状态!然而,当我们跟踪查询时,我们注意到SQL确实返回了数据。由于某种原因,Entity Framework没有创建代理,对Payment.Recipient的任何引用都是null。

此外,当我们对现有ID(在长度更改之前)执行请求时,我们可以毫无问题地获得结果。

那么问题来了:

  1. 为什么本地工作良好(包括ID长度),但远程(在生产中)不工作?

    • 可能会有什么类型的数据库设置影响这个变化呢?
  2. 原始SQL执行在生产环境中有效,但创建代理EF无效,为什么?

任何帮助都将非常棒!

-- 添加原始SQL --

=========================================================
ID: 'bf08bdf4-a9d5-42e0-9236-a65faa4cc6ea                  '
=========================================================
SELECT 
    [Extent1].[TransactionId] AS [TransactionId],
    [Extent1].[RecipientId] AS [RecipientId],
    [Extent2].[AccountId] AS [AccountId], 
    [Extent2].[Name] AS [Name],
    FROM   [dbo].[Payment] AS [Extent1]
    INNER JOIN [dbo].[Account] AS [Extent2] ON [Extent1].[RecipientId] = [Extent2].[AccountId]
=========================================================
Recipient is null...

良好的请求

=========================================================
ID: 'f0e9beef                               ' 
=========================================================
SELECT 
    [Extent1].[TransactionId] AS [TransactionId],
    [Extent1].[RecipientId] AS [RecipientId],
    [Extent2].[AccountId] AS [AccountId], 
    [Extent2].[Name] AS [Name],
    FROM   [dbo].[Payment] AS [Extent1]
    INNER JOIN [dbo].[Account] AS [Extent2] ON [Extent1].[RecipientId] = [Extent2].[AccountId]
=========================================================
Recipient is not null!
RecipientId: '835cbb56                          '    
Name: John Doe

!! 更新 !!

我正在调查来自RAW sql的结果,并发现新更改的属性上保存了额外的空格...

我偶然发现了Ro Miller的这篇文章:

http://romiller.com/2014/10/20/ef6-1workaround-trailing-blanks-issue-in-string-joins/

说明字符串截断可能是一个问题... 让我们找出来...


已解决。谢谢你 ;) - Erik5388
流畅的API适用于Transaction,而不是Payment。您能否还展示一下它正在生成的SQL语句?(并且展示一个通过SQL加载但未加载到数据集中的ID?) - Rob
1个回答

2

是的,

在更改ID字段长度后,我发现在LINQ to Entity查询返回时出现了不必要的“空格”。

通过遵循Ro Miller的拦截器指南,我能够确保所有字符串字段在传输到数据库之前都被修剪过。

http://romiller.com/2014/10/20/ef6-1workaround-trailing-blanks-issue-in-string-joins/

需要注意的是,拦截器功能仅在EF6.1中最近才可用。

希望这能对某些人有所帮助... 我今天花了11个小时来解决这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,