首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何修复“应用单个聚合的集合必须为空或恰好包含一项”InvalidOperationException?

如何修复“应用单个聚合的集合必须为空或恰好包含一项”InvalidOperationException?
EN

Stack Overflow用户
提问于 2017-06-16 14:15:09
回答 1查看 698关注 0票数 4

执行此查询后,我得到了一个InvalidOperationException:“应用单个聚合的集合必须为空或恰好包含一项”。

代码语言:javascript
复制
List<int> olsesUsedForTaskCompletion = new List<int>();
olsesUsedForTaskCompletion.AddRange(task.OrderLineSpecifications_QtysCompleted.Select(ols => ols.Key).ToList());

var allRelatedTasks = (from t in new XPQuery<Core.Model.Task.Task>(session, true)
                       join ols in new XPQuery<OrderLineSpecification>(session, true)
                       on t.PickSpecification equals ols.PickSpecification
                       where t.PickSpecification == task.PickSpecification
                          && t.Status != TaskStatuses.Cancelled
                          && olsesUsedForTaskCompletion.Contains(ols.Oid)
                       select t).ToList();

我希望当我做join时,只得到具有特定Id的OLS。我做错了什么?

这是堆栈跟踪:

代码语言:javascript
复制
at DevExpress.Xpo.Helpers.InTransactionLoader.ProcessException(Exception ex)
   at DevExpress.Xpo.Helpers.InTransactionLoader.ProcessAnalyzeAndExecQuery()
   at DevExpress.Xpo.Helpers.InTransactionLoader.Process()
   at DevExpress.Xpo.Helpers.InTransactionLoader.GetObjects(ObjectsQuery[] queries)
   at DevExpress.Xpo.Helpers.InTransactionLoader.GetObjects(Session session, ObjectsQuery[] queries)
   at DevExpress.Xpo.Session.<>c__DisplayClass16.<GetObjectsInTransaction>b__14()
   at DevExpress.Xpo.Logger.LogManager.Log[T](String category, LogHandler`1 handler, MessageHandler`1 createMessageHandler)
   at DevExpress.Xpo.Session.GetObjectsInTransaction(XPClassInfo classInfo, CriteriaOperator condition, SortingCollection sorting, Int32 skipSelectedRecords, Int32 topSelectedRecords, Boolean selectDeleted)
   at DevExpress.Xpo.XPQueryBase.SessionGetObjects(XPClassInfo classInfo, CriteriaOperator condition, SortingCollection sorting, Int32 skipSelectedRecords, Int32 topSelectedRecords, Boolean selectDeleted)
   at DevExpress.Xpo.XPQueryBase.GetObjects()
   at DevExpress.Xpo.XPQueryBase.Enumerate(Type type)
   at DevExpress.Xpo.XPQuery`1.GetEnumerator()
   at DevExpress.Xpo.XPQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Davanti.WMS.Services.Implementation.Outbound.OrderLineSpecificationStatusService.ChangeStatusToPickedToShipToStageOrStaged(Session session, IList`1 tasks, IList`1 olsWithoutTasks) in c:\Corax\DAV_WMS\DEV\SRC\APP\WMS\Davanti.WMS.Services.Implementation\Outbound\OrderLineSpecificationStatusService.cs:line 471

更新:在经历了一些挣扎之后,这里是我所做的:-用了另一种方法。我不知道您是否能理解它的业务逻辑,但我首先用OLS生成了一个列表,然后用它生成了另一个带有pick规范的列表。稍后,我对任务执行一个简单的查询。

代码语言:javascript
复制
// compose list of olses for which status will be updated
    List<OrderLineSpecification> olSpecs = (from ols in new XPQuery<OrderLineSpecification>(session, true)
                                            where ols.Status != OrderLineSpecificationStatus.Cancelled 
                                                    //...
                                                    && ols.PickSpecification == task.PickSpecification
                                                    && (olsesUsedForTaskCompletion.Count == 0
                                                        || (olsesUsedForTaskCompletion.Contains(ols.Oid) && ols.QtyOrdered == ols.QtyPicked))
                                            select ols).ToList();

    var pickSpecificationKeys = (from ols in olSpecs select ols.PickSpecification.Oid).Distinct().ToList();

    var allRelatedTasks = (from t in new XPQuery<Core.Model.Task.Task>(session, true)
                            where pickSpecificationKeys.Contains(t.PickSpecification.Oid)
                                    && t.Status != TaskStatuses.Cancelled
                            select t).ToList();

我只希望这能行得通,不管客户端的数据库结构、双重引用还是其他的……:)

EN

回答 1

Stack Overflow用户

发布于 2017-06-19 23:31:43

查询中的Select部分实例化一个持久对象,这意味着结果序列中的每个元素都是唯一的(一个持久对象不能两次加载到同一个会话中)。这就是为什么查询被转换为单个聚合函数的原因。错误的原因是,连接表达式中的innerKey和outerKey的匹配可能会产生从外部序列中选择的重复条目。3.

如果您的场景中不需要重复项,则需要修复数据库中的数据或重写查询以考虑到这一点。例如,您可以使用"join into“操作符对重复的记录进行分组:

代码语言:javascript
复制
from t in new XPQuery<Core.Model.Task.Task>(session, true)
   join ols in new XPQuery<OrderLineSpecification>(session, true)
   on t.PickSpecification equals ols.PickSpecification
   into tg
   where tg.key == task.PickSpecification
      && tg.Any(gi.Status != TaskStatuses.Cancelled && olsesUsedForTaskCompletion.Contains(ols.Oid))
   select t

在某些情况下,替换查询中的序列也可能有助于避免错误,但在结果序列中会有重复的对象引用:

代码语言:javascript
复制
from ols in new XPQuery<OrderLineSpecification>(session, true)
   join t in new XPQuery<Core.Model.Task.Task>(session, true)
   on ols.PickSpecification equals t.PickSpecification
   where ols.PickSpecification == task.PickSpecification
      && t.Status != TaskStatuses.Cancelled
      && olsesUsedForTaskCompletion.Contains(ols.Oid)
   select t

如果您对结果序列中的重复记录没有意见,我建议您只需向Select语句添加一个投影,这样查询就不需要实例化持久对象。

代码语言:javascript
复制
from t in new XPQuery<Core.Model.Task.Task>(session, true)
   join ols in new XPQuery<OrderLineSpecification>(session, true)
   on t.PickSpecification equals ols.PickSpecification
   where t.PickSpecification == task.PickSpecification
      && t.Status != TaskStatuses.Cancelled
      && olsesUsedForTaskCompletion.Contains(ols.Oid)
   select new { SomeProperty = t.SomeProperty, AnotherProperty = t.AnotherProperty }

PS:如果以上方法都不适用于您的特定情况,请直接联系DevExpress Support Service。您的问题对于XPO来说太具体了,所以您很可能会在那里获得合格的答案。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44582031

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档