EF6延迟加载:添加时加载整个集合?

时间:2018-11-10 08:02:31

标签: entity-framework entity-framework-6

我的实体上具有以下集合导航属性:

public virtual ICollection<OrderIntegrationLogEntry> LogEntries { get; set; }

OrderIntegrationLogEntry实体具有一些配置:

this.HasKey(i => new {i.Id, i.IntegrationId});
this.HasRequired(i => i.Integration).WithMany(i => i.LogEntries).HasForeignKey(i => i.IntegrationId).WillCascadeOnDelete(true);

似乎这行代码:

integration.LogEntries.Add(new OrderIntegrationLogEntry
{
    Id = Guid.NewGuid(),
    CreatedUtc = DateTime.UtcNow,
    Message = message,
    Level = level,
    Detail = detail
});

...导致查询加载集合的内容:

SELECT [Extent1].[Id] AS [Id], [Extent1].[IntegrationId] AS [IntegrationId],
[Extent1].[CreatedUtc] AS [CreatedUtc], [Extent1].[Level] AS [Level],
[Extent1].[Message] AS [Message], [Extent1].[Detail] AS [Detail]
FROM [dbo].[OrderIntegrationLogEntries] AS [Extent1]
WHERE [Extent1].[IntegrationId] = @EntityKeyValue1

我没想到这一点:难道不应该只是增加一次吗?我需要以其他方式配置吗?

2 个答案:

答案 0 :(得分:1)

如Ivan所述,您将LogEntries称为getter,这会导致延迟加载。

如果您不想关闭延迟加载,则不必将日志实体添加到父级的Navigation属性中,只需设置新实体的IntegrationId和SaveChanges()。例如

const l = 100; // length
const tf = l * 2 / 5; // two fifths of length

const ctx = document.getElementById("canvas").getContext("2d");
ctx.translate(20, 40); // just for display

ctx.moveTo(0,0);
ctx.bezierCurveTo(tf,-(l-tf),l-tf,l-tf,l,0);

ctx.lineWidth = 2;
ctx.stroke();

如果这是SQL Server(可能还有其他平台),则使用顺序GUID生成。插入带有随机GUID的行作为其前导键列不必要地昂贵。对于SQL Server,您可以在数据库中使用NEWSEQUENTIALID()函数作为默认值或在客户端上生成顺序GUID。

<canvas id="canvas" width="200" height="100">

How to Generate Sequential GUIDs for SQL Server in .NET

如果希望主要基于逐个集成访问日志条目,则还应该考虑翻转键列的顺序。它将一起存储集成的日志条目。 EG

var entry = new OrderIntegrationLogEntry()
{
    Id = Guid.NewGuid(),
    IntegrationId = integration.Id,
    CreatedUtc = DateTime.UtcNow,
    Message = message,
    Level = level,
    Detail = detail
);
db.OrderIntegrationLogEntries.Add(entry);
db.SaveChanges();

如果您不在Windows上,则可以通过从随机GUID开始并递增4个低位字节来滚动自己的顺序GUID生成器。 GUID仅在AppDomain中是顺序的,但这没关系。

类似这样的东西:

  public class SQLGuidUtil
  {
      [DllImport("rpcrt4.dll", SetLastError = true)]
      static extern int UuidCreateSequential(out Guid guid);

      public static Guid NewSequentialId()
      {
        Guid guid;
        UuidCreateSequential(out guid);
        var s = guid.ToByteArray();
        var t = new byte[16];
        t[3] = s[0];
        t[2] = s[1];
        t[1] = s[2];
        t[0] = s[3];
        t[5] = s[4];
        t[4] = s[5];
        t[7] = s[6];
        t[6] = s[7];
        t[8] = s[8];
        t[9] = s[9];
        t[10] = s[10];
        t[11] = s[11];
        t[12] = s[12];
        t[13] = s[13];
        t[14] = s[14];
        t[15] = s[15];
        return new Guid(t);
      }
  }

答案 1 :(得分:0)

为了启用延迟加载,EF创建了从模型派生的代理类。在这些类中,它重写导航属性以实现延迟加载。这就是为什么应该定义导航属性virtual以便EF可以覆盖它们的原因。 调用integration.LogEntries.Add时,将调用LogEntries属性的getter,它会触发延迟加载操作。

您可以使用以下代码暂时禁用延迟加载:

context.Configuration.LazyLoadingEnabled = false;