更改值适用于急切加载,但不适用于 linq 和 ef 中的延迟加载
这不是“问题”问题,而是“为什么会发生这种情况”问题。
var chapters = story.Chapters.Select(
ch => new ChapterDisplayViewModel {
Id = ch.Id,
Number = ch.Number});
首先我想获取一些数据。故事是 Story
类型的实体类型,它与 Chapter
具有一对多关系,我想更改我得到的章节集合中的一些数据,所以我写了一些条件,如果因此,更改值
if(chapters.Any(c => c.Number == chapterNum))
chapters.Where(c => c.Number == chapterNum).Single().IsSelected = true;
,然后我将数据发送到视图,但问题是:
由于延迟加载,没有任何更改,即使在将数据发送到视图之后,我所做的更改也没有被触发,为什么?我做了一个分配语句,不应该将数据传递到视图触发它?
解决方案当然是使用 ToList 立即执行查询
var chapters = story.Chapters.Select(
ch => new ChapterDisplayViewModel {
Id = ch.Id,
Number = ch.Number}).ToList();
我只想解释一下行为
this is not 'a problem' question , but 'why this happens' question.
var chapters = story.Chapters.Select(
ch => new ChapterDisplayViewModel {
Id = ch.Id,
Number = ch.Number});
first i want to get some data. story is an entity type of type Story
and it has One To Many relation with Chapter
i want to change some data in the chapters collection that i got so i write some condition if so change the value
if(chapters.Any(c => c.Number == chapterNum))
chapters.Where(c => c.Number == chapterNum).Single().IsSelected = true;
and then i send the data to the view but the problem is :
nothing is changed due to lazy loading , the change that i made wasn't triggerd even after sending the data to the view , Why ? i made an assigment statment and shouldn't passing the data to the view trigger it ?
the solution was of course using ToList to execute the query immediately
var chapters = story.Chapters.Select(
ch => new ChapterDisplayViewModel {
Id = ch.Id,
Number = ch.Number}).ToList();
i just want an explanation to the behavior
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因为您说您的
Story
类上有一个延迟加载的集合Chapters
,所以我假设Chapters
实际上是动态代理对象的集合。如果您使用探查器查看数据库中发生的情况,您将看到这一行......在数据库中执行一个查询,该查询查询所有
Chapter
对象(投影到ChapterDisplayViewModel< /code> 不会发生在数据库中)。这是唯一的数据库查询。以下......
在内存中已延迟加载的
Chapters
集合上执行。投影发生在此时。但这意味着
Single
运算符具体化了一个ChapterDisplayViewModel
对象,这意味着:内部某处发生了一个new ChapterDisplayViewModel
。对此进行简单检查:sameObjects
为false
,这意味着Single
不仅仅返回对内存中已存在的 ViewModel 对象的引用,而是创建新实例其中。当您在第一个查询中应用
ToList
时,ViewModel 会立即具体化为内存中的 ViewModel 集合,而Single
将仅返回对匹配但已存在的引用目的。sameObjects
将为true
。因此,如果没有
ToList
,您将在刚刚物化的对象上设置IsSelected
属性,您不再引用该对象,因此会立即在垃圾收集中消失。使用ToList
,您可以在内存集合内的唯一对象上设置属性。当您在视图中使用此集合时,该标志仍然存在。Because you say that you have a lazily loaded collection
Chapters
on yourStory
class I assume thatChapters
is actually a collection of dynamic proxy objects. If you look what happens in the database with a profiler you will see that this line ...... executes a query in the database which queries all
Chapter
objects (the projection intoChapterDisplayViewModel
doesn't happen in the database). And that's the only database query. The following ...... is executed in memory on the already lazily loaded collection of
Chapters
. The projection happens at this point.But this means that the
Single
operator materializes aChapterDisplayViewModel
object, it means: There happens anew ChapterDisplayViewModel
somewhere internally. Simple check for this:sameObjects
isfalse
which meansSingle
doesn't simply return references to ViewModel objects which are already in memory but creates new instances of them.When you apply
ToList
in the first query the ViewModels are materialized at once into a in-memory collection of ViewModels andSingle
will simply return a reference to the matching, but already existing object.sameObjects
will betrue
.So, without
ToList
you are setting theIsSelected
property on a just materialized object which you don't reference anymore and therefore disappears in garbage collection immediately. WithToList
you are setting the property on the unique object inside of the in-memory collection. When you use this collection in your view the flag is still there.