有了这个查询,我得到一个InvalidOperationException:“应用Single聚合的集合必须为空或者只包含一个项目”.
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();
我希望在我加入时只获得具有特定ID的OLS.我究竟做错了什么?
这是堆栈跟踪:
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列表,然后从中生成另一个带有选择规范的列表.后来我对Tasks进行了简单的查询.
// 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();
我只希望这会工作,无论客户的数据库结构,duble参考还是…… 🙂
最佳答案 查询中的Select部分实例化一个持久对象,这意味着结果序列中的每个元素都是唯一的(持久对象不能两次加载到同一个Session中).这就是将查询转换为单个聚合函数的原因.错误的原因是在Join表达式中匹配innerKey和outerKey可能会产生从外部序列中选择的项的重复条目.
如果在您的方案中不期望重复,则需要修复数据库中的数据或重写查询以将此考虑在内.例如,您可以使用“join into”运算符对重复记录进行分组:
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
替换查询中的序列也可能有助于避免某些情况下的错误,但您将在结果序列中有重复的对象引用:
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语句添加一个投影,以便查询不需要实例化持久对象.
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来说过于具体,因此您可能会在那里获得合格的答案.