可以在EntityFramework中懒惰的列值吗?

发布于 2025-01-19 16:35:52 字数 796 浏览 0 评论 0原文

数据库中有一个表,该表具有列IDnamegrouptext文本列中的值大小很大(约1MB至3 MB)。

如果我使用EntityFramework更新一行,

public async Task UpdateName(int id, string name, CancellationToken cancellationToken)
{
    var record = await dbContext.TheTables.FirstOrDefaultAsync(t => t.Id == id, cancellationToken) 
        ?? throw new ObjectNotFoundException();
    
    record.Name = newName;
    dbContext.SaveChangesAsync(cancellationToken);
}

则运行可能很昂贵,因为text列的大小很大。

dbContext.thetables.where(t => t.group ==“ theGroupName”)之类的查询可能更昂贵!

我的问题是“是否有一种更便宜的方法来查询数据和/或更新数据??? 可以懒惰 lazy-load-tagon?''如何?”

There is a table in the database that has columns Id, Name, Group, and Text. and sizes of values in the Text column are big (about 1MB to 3 MB).

If I use EntityFramework to update one row

public async Task UpdateName(int id, string name, CancellationToken cancellationToken)
{
    var record = await dbContext.TheTables.FirstOrDefaultAsync(t => t.Id == id, cancellationToken) 
        ?? throw new ObjectNotFoundException();
    
    record.Name = newName;
    dbContext.SaveChangesAsync(cancellationToken);
}

This can be expensive to run since the size of the Text column is big.

The query like dbContext.TheTables.Where(t => t.Group == "TheGroupName") can be even more expensive!

My question is "Is there a cheaper way to query data and/or update the data??? Can Text be lazy-loaded and how?"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

野稚 2025-01-26 16:35:53

AFAIK EF不支持懒惰的加载值属性,我记得Nhibernate确实具有此功能。

典型的推荐关系方法在您昂贵时,但是很少需要的字段是将这些字段分开以使用一对一相关的表。即thetable.thetabledetails,这是您昂贵的领域所在的地方。

这样,您可以有效地与基础桌实体一起工作,并且只能在需要时击中昂贵的东西。 (通常一次是一个记录)

请注意,在您的示例中,您在savechangesasync() call中缺少等待

阅读信息时,请利用投影以排除昂贵的字段/关系,而不是返回实体,渴望加载或冒着懒惰的负载调用,以获取昂贵的值。

还有一个更“ hacky”的选项,除非可能是最后的度假胜地,否则我不建议这样做:

public async Task UpdateName(int id, string name, CancellationToken cancellationToken)
{
    var recordExists = dbContext.TheTables.Any(x => x.Id == id);
    if (!recordExists) throw new ObjectNotFoundException();
    
    var record = dbContext.TheTables.Local.SingleOrDefault(x => x.Id == id);
    if (record != null)
        record.Name = newName;
    else
    {
        record = new Record { Id = id, Name = newName };
        dbContext.Attach(record);
        dbContext.Entry(record).Property(x => x.Name).IsModified = true;
    }
    await dbContext.SaveChangesAsync(cancellationToken);
}

这实际上是检查记录是否在不加载的情况下存在。然后,如果DBContext已经在跟踪它,则我们检查本地高速缓存,如果是这样,我们设置了名称。如果没有跟踪,我们将创建一个带有ID和新名称的新最小实例,将名称标记为修改。

这样的方法应用作最后的度假胜地,因为“记录”实例可以是完整的跟踪实体实例,也可以是跟踪的不完整实例。以后通过该实体继续或返回实体的修改会导致潜在的运行时错误。实际上,如果附加和更新实体的存根,则应在savechanges()调用后将其分离和处置。

AFAIK EF doesn't support lazy loading value properties, where as I recall NHibernate does have this capability.

The typical recommended relational approach when you have expensive, but seldom needed fields is to split those fields off to use a one-to-one related table. I.e. TheTable.TheTableDetails which is where your expensive fields would live.

This way you can work efficiently with the base table entity and only hit the expensive stuff when needed. (Typically one record at a time)

Note that in your example you are missing an await on your SaveChangesAsync() call as well.

When reading information, leverage projection to exclude expensive fields/relationships rather that returning entities and either eager loading or risking a lazy load call fetching expensive values.

There is also a more "hacky" option that I wouldn't recommend except as possibly a last resort:

public async Task UpdateName(int id, string name, CancellationToken cancellationToken)
{
    var recordExists = dbContext.TheTables.Any(x => x.Id == id);
    if (!recordExists) throw new ObjectNotFoundException();
    
    var record = dbContext.TheTables.Local.SingleOrDefault(x => x.Id == id);
    if (record != null)
        record.Name = newName;
    else
    {
        record = new Record { Id = id, Name = newName };
        dbContext.Attach(record);
        dbContext.Entry(record).Property(x => x.Name).IsModified = true;
    }
    await dbContext.SaveChangesAsync(cancellationToken);
}

What this essentially does is check that the record exists without loading it. We then check the local cache in case the DbContext is already tracking it, if so we set the Name. If it isn't tracked we create a new minimal instance with the ID and the new name, marking the name as modified.

Such an approach should be used as a last resort and carefully as the "record" instance could be either a complete tracked entity instance, or a tracked incomplete instance. Later modifications that pass that entity onwards or return the entity would lead to potential runtime bugs. Realistically if that stub of an entity is attached and updated, it should be detached and disposed of after the SaveChanges() call.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文