Linq困境 - 需要CollectionType

时间:2012-06-27 15:32:57

标签: linq entity-framework c#-4.0 linq-to-entities

为什么我的linq查询不起作用?

我怀疑它可能与延迟加载有关。 似乎在linqpad中工作。

public IList<PaymentDto> GetDocumentPayments(int documentId, bool? allowRepeatPayments, byte[] paymentStatuses, int[] paymentMethods)
    {
        using (var ctx = ObjectContextManager<MyDataContext>.GetManager("MyDataContext"))
        {
            var payments = new List<PaymentDto>();

            var ps = new List<byte>();        
            if (paymentStatuses != null)
            {
                ps = paymentStatuses.ToList();
            }

            var pm = new List<int>();
            if (paymentMethods != null)
            {
                pm = paymentMethods.ToList();
            }

            IQueryable<Payment> data = 
                   from payment in ctx.ObjectContext.Documents.OfType<Payment>()
                   where
                       ps.Contains(payment.Status) && 
                       pm.Contains(payment.Method) &&
                       payment.DocumentId == documentId &&
                       (allowRepeatPayments == null || payment.AllowRepeatPayments == allowRepeatPayments)
                   orderby payment.Id
                   select payment;

            foreach (var p in data) // Fails here
            {
                payments.Add(ReadData(p));
            }

            return payments;
        }
    }

引发错误:需要CollectionType。 参数名称:collectionType。

2 个答案:

答案 0 :(得分:1)

(allowRepeatPayments == null || payment.AllowRepeatPayments == allowRepeatPayments)这样的构造可以对查询做有趣的事情。试试当你这样做时会发生什么:

if (allowRepeatPayments.HasValue)
{
    data = data.Where(p => p.AllowRepeatPayments == allowRepeatPayments);
}

您可以对paymentStatusespaymentMethods执行相同操作。

它可能会解决您的问题,但如果没有,它仍然是一种改进,因为只有在必要时才会添加条件,而不是SQL时它就不会混乱。

答案 1 :(得分:0)

在将LINQ查询转换为SQL时,框架的内部方法抛出异常,并使用与您正在使用的空检查相同类型的构造(例如

.Where(data => x & y & (values == null || values.Contains(data.value)));)

我刚刚在运行最早版本的.Net 4 RTM (4.0.30319.1)的服务器上遇到了同样的异常。 它来自

   exception : System.ArgumentException: A CollectionType is required.
   Parameter name: collectionType

   at System.Data.Common.CommandTrees.ExpressionBuilder.Internal.ArgumentValidation.ValidateNewEmptyCollection(TypeUsage collectionType, DbExpressionList& validElements)
   at System.Data.Objects.ELinq.ExpressionConverter.NewArrayInitTranslator.TypedTranslate(ExpressionConverter parent, NewArrayExpression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) ...

错误在互联网上非常罕见,并且在相同的条件和更新的版本中不会发生,所以它似乎已经在更新版本的.Net上得到修复。

Gert Arnold的建议也可能允许避免错误,但上面的表格经常被使用(就像SQL对应的那样)并且它很简短且有用。

因此,对于那些仍然遇到此错误并且不理解为什么它在某台计算机上工作而有时不能解决的人,我建议检查他们的.Net FW版本