我在事件处理程序中执行了两个相似但不同的Odata服务操作调用(相同的服务操作,不同的参数)。单步执行代码,我可以看到每个查询的CreateQuery<> call产生不同的查询URI,并且当通过浏览器请求时,返回的结果是正确的。现在有点笨蛋!第二个查询总是返回与第一个查询相同的结果,除非我指定MergeOption = OverwriteChanges。这是我如何调用svc操作的简化视图:
List<Listing> whereToDine = Container.CreateQuery<Listing>("SearchListings")
.AddQueryOption("listingTypeIds", "'14'")
.AddQueryOption("cityId", CityId.ToString())
.AddQueryOption("radius", SearchRadius.ToString())
.AddQueryOption("skipIndex", "0")
.AddQueryOption("pageSize", (PageSize * NumPages).ToString())
.AddQueryOption("sortType", "'name'").ToList<Listing>();
有人知道为什么会这样吗?
答案 0 :(得分:1)
客户端跟踪实体(假设列表是实体类型)。因此,在评估查询时,Container(DataServiceContext)保存对其返回的所有实体的引用。
这是必要的,以便能够跟踪实体的更改,以便在您调用SaveChanges时,上下文知道哪些实体需要向服务器发送请求以进行更新。
目前,客户端不执行属性级别跟踪,因此它只知道整个实体是否发生了变化。如果它上面的单个属性发生了变化,那就不行了。
因此,当它读取来自服务器的数据并且响应包含客户端已经跟踪的实体时,它必须决定来自服务器的数据是要使用的数据还是应该使用客户端上的值(基本上在那时它有两个版本的同一个实体,一个来自客户端,一个来自服务器)。
MergeOption是告诉客户在这种情况下该做什么的设置。
默认情况下客户端值为win,这样的想法是,如果您在客户端上更改了某些值,则不希望服务器中的值覆盖您的更改,直到您通过SaveChanges提交它们。
因此,在第一次调用服务操作时,客户端从服务器获取实体(第一次)并获得结果。在第二个调用中,您可能获得相同的实体,但其中包含新值。但客户端的默认设置是保留客户端值,因此查询的评估会有效地从服务器中丢弃传入的数据。
MergeOption是告诉客户端做什么的正确方法。