我的实体上具有以下集合导航属性:
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
我没想到这一点:难道不应该只是增加一次吗?我需要以其他方式配置吗?
答案 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;