访问LINQ to Entities set

时间:2017-04-19 20:40:50

标签: c# linq

我在Linq查询中的字符串上使用Split方法,但只需要第二个元素。我在下面的代码中得到一个“System.InvalidOperationException:'无法识别的表达式节点:ArrayIndex'”:

    var RMA_stops_all = (from rma in rDb.DistributionStopInformations
                         join line in rDb.DistributionLineItems on rma.UniqueIdNo equals line.UniqueIdNo
                         where line.RmaNumber != null 
                         &&
                         (line.DatetimeCreated > Convert.ToDateTime(dateToCheck_rma) &&
                         line.DatetimeCreated < Convert.ToDateTime(dateToCheck_rma).AddDays(7))
                         && rma.CustomerNo == TNGCustNo
                         select new
                         {
                             dtCreated = line.DatetimeCreated,
                             UniqueIdNo = rma.UniqueIdNo,
                             RmaNumber = line.RmaNumber,
                             RmaOriginalUniqueId = line.RmaOriginalUniqueId,
                             ItemSequenceNo = line.ItemSequenceNo,
                             ItemNumber = line.ItemNumber,
                             goodRMA_flag =  line.RmaNumber.Contains("/078"),
                             rmaGood = line.RmaNumber.Split(new string[] { "/" }, StringSplitOptions.None)[1]
                         }).ToArray();

如果我删除数组上的[1]它可以工作,我可以使用以下方法访问整个数据集的两个元素:

  foreach (var item in RMA_stops_all)
        {
         var right = RMA_stops_all.First().rmaGood[1];
         var left = RMA_stops_all.First().rmaGood[0];
            Console.WriteLine("left {0} - right{1} ",left.ToString(), right.ToString());
        }
编辑 - 呃。上面的“测试”是完全没用的(如同轻轻指出的那样) - 但是,下面确实证明它正常工作(一些返回的值只有1个元素,因此额外的if块 - 输出是预期的:

 foreach (var item in RMA_stops_all)
            {
                string right, left;
                if (item.rmaGood.Length == 1)
                {
                     left = item.rmaGood[0].ToString();
                     right = "Not there";
                }
                else
                {
                 left = item.rmaGood[0].ToString();
                 right = item.rmaGood[1].ToString();
                }
                Console.WriteLine("left {0} - right{1} ", left, right);
            }

dbMonitor的SQL输出:

SELECT t2.datetime_created AS "DatetimeCreated", 
       t1.unique_id_no AS "UniqueIdNo", 
       t2.rma_number AS "RmaNumber", 
       t2.rma_original_unique_id AS "RmaOriginalUniqueId",
       t2.item_sequence_no AS "ItemSequenceNo", 
       t2.item_number AS "ItemNumber", 
       (t2.rma_number LIKE :p3) OR (t2.rma_number LIKE :p4) AS "C1",
       t2.rma_number AS "RmaNumber1"
FROM cops_reporting.distribution_stop_information t1
INNER JOIN cops_reporting.distribution_line_items t2 
    ON t1.unique_id_no = t2.unique_id_no
WHERE (t2.rma_number IS NOT NULL) 
   AND (t2.datetime_created > :p0)
   AND (t2.datetime_created < :p1)
   AND (t1.customer_no = :p2)

2 个答案:

答案 0 :(得分:1)

我没有意识到Linq to Entities可以直接访问某些SQL函数,所以这可能对您有用:

var RMA_stops_all = (from rma in rDb.DistributionStopInformations
                     join line in rDb.DistributionLineItems on rma.UniqueIdNo equals line.UniqueIdNo
                     where line.RmaNumber != null 
                     &&
                     (line.DatetimeCreated > Convert.ToDateTime(dateToCheck_rma) &&
                     line.DatetimeCreated < Convert.ToDateTime(dateToCheck_rma).AddDays(7))
                     && rma.CustomerNo == TNGCustNo
                     select new
                     {
                         dtCreated = line.DatetimeCreated,
                         UniqueIdNo = rma.UniqueIdNo,
                         RmaNumber = line.RmaNumber,
                         RmaOriginalUniqueId = line.RmaOriginalUniqueId,
                         ItemSequenceNo = line.ItemSequenceNo,
                         ItemNumber = line.ItemNumber,
                         goodRMA_flag =  line.RmaNumber.Contains("/078"),
                         rmaGood = line.RmaNumber.Substring(line.RmaNumber.IndexOf("/")+1)
                     }).ToArray();

假设RmaNumber看起来像#/#并且没有你想要避免的额外斜杠。

答案 1 :(得分:0)

我不明白为什么没有索引操作它会工作,你的SQL似乎没有反映相同的Linq代码(你使用过LinqPad吗?),但我建议你自己做.ToArray( )无论如何,将分割/索引移动到客户端:

var RMA_stops_all = (from rma in rDb.DistributionStopInformations
                     join line in rDb.DistributionLineItems on rma.UniqueIdNo equals line.UniqueIdNo
                     where line.RmaNumber != null 
                     &&
                     (line.DatetimeCreated > Convert.ToDateTime(dateToCheck_rma) &&
                     line.DatetimeCreated < Convert.ToDateTime(dateToCheck_rma).AddDays(7))
                     && rma.CustomerNo == TNGCustNo
                     select new
                     {
                         dtCreated = line.DatetimeCreated,
                         rma.UniqueIdNo,
                         line.RmaNumber,
                         line.RmaOriginalUniqueId,
                         line.ItemSequenceNo,
                         line.ItemNumber,
                         goodRMA_flag =  line.RmaNumber.Contains("/078"),
                     }).AsEnumerable().Select(r => new {
                         r.dtCreated,
                         r.UniqueIdNo,
                         r.RmaNumber,
                         r.RmaOriginalUniqueId,
                         r.ItemSequenceNo,
                         r.ItemNumber,
                         r.goodRMA_flag,
                         rmaGood = r.RmaNumber.Split(new string[] { "/" }, StringSplitOptions.None)[1]
                     });

顺便说一句,您不必为简单的访问器表达式重复字段/属性名称,因此我将其从原始选择中删除。此外,如果您可以使用双重间接,则可以在第二个选择中包含r。