可以在EntityFramework中懒惰的列值吗?
数据库中有一个表,该表具有列ID
,name
,group
和text
。 文本
列中的值大小很大(约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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
AFAIK EF不支持懒惰的加载值属性,我记得Nhibernate确实具有此功能。
典型的推荐关系方法在您昂贵时,但是很少需要的字段是将这些字段分开以使用一对一相关的表。即thetable.thetabledetails,这是您昂贵的领域所在的地方。
这样,您可以有效地与基础桌实体一起工作,并且只能在需要时击中昂贵的东西。 (通常一次是一个记录)
请注意,在您的示例中,您在
savechangesasync()
call中缺少等待
。阅读信息时,请利用投影以排除昂贵的字段/关系,而不是返回实体,渴望加载或冒着懒惰的负载调用,以获取昂贵的值。
还有一个更“ hacky”的选项,除非可能是最后的度假胜地,否则我不建议这样做:
这实际上是检查记录是否在不加载的情况下存在。然后,如果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 yourSaveChangesAsync()
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:
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.