尝试使用contains编写LINQ查询并从List开始

时间:2017-05-04 12:50:02

标签: c# linq lambda

在C#中使用VS 2017 我有一个扩展范围的工作解决方案。 最初它只需要返回一个数据集,其中如果line.RMANumber包含或以两个不同的变量开始,则goodRMA_flag被设置为true。

这是原始代码,工作正常:

string mask1 = "/078";
string mask2 = "078";

        //start with all of them, flag the good and bad
        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
                             {
                                 DatetimeCreated = line.DatetimeCreated,
                                 UniqueIdNo = rma.UniqueIdNo,
                                 RmaNumber = line.RmaNumber,
                                 RmaOriginalUniqueId = line.RmaOriginalUniqueId,
                                 ItemSequenceNo = line.ItemSequenceNo,
                                 ItemNumber = line.ItemNumber,
                                 goodRMA_flag = (line.RmaNumber.Contains(mask1) || line.RmaNumber.StartsWith(mask2)),
                                 RMA_cleanedUp = line.RmaNumber.Substring(line.RmaNumber.IndexOf("/") + 1)
                             }).ToArray();

现在他们已经将要求扩展到可能需要任意数量的面具的地方。 我正在使用以下代码构建所有需要匹配的列表:

  int startingMask = 75;
            int numberNumberNeeded = 10;
            List<string> masksContains = new List<string>();
            List<string> masksStartsWith = new List<string>();

            while (numberNumberNeeded > 0)
            {
            string newMask = (++startingMask).ToString().PadLeft(3, '0');
                masksStartsWith.Add(newMask);
                newMask = newMask.PadLeft(4, '/');
                masksContains.Add(newMask);
                numberNumberNeeded--;
            }

现在我有了列表,我想将goodRMA_flag的行更改为:

goodRMA_flag = (line.RmaNumber.Contains(masksContains) || line.RmaNumber.StartsWith(masksStartsWith)),

我假设我需要某种Lamda,但是尽管有多次波动,我还是无法使语法正确。

编辑: 使用 -

    goodRMA_flag = (masksContains.Any(masks => line.RmaNumber.Contains(masks)) ||
 masksStartsWith.Any(masks => line.RmaNumber.StartsWith(masks))),

给出运行时错误: &#34; System.NotSupportedException:&#39;本地序列不能用于查询运算符的LINQ to SQL实现,但Contains()运算符除外。&#39;

解决方案 - 这是最终的工作代码供参考:

 //a integer that we are starting with - this needs to come from
 //a database at some point
        int startingMask = 75;
        //how far ahead to look
        int qtyNeeded= 10;
        //will hold the strings that RMA_Number needs to contain
        List<string> masksContains = new List<string>();
        //will hold the strings that RMA_Number needs to start with
        List<string> masksStartsWith = new List<string>();

        //Build the two lists
        while (qtyNeeded> 0)
        {
        string newMask = (++startingMask).ToString().PadLeft(3, '0');
            masksStartsWith.Add(newMask);
            newMask = newMask.PadLeft(4, '/');
            masksContains.Add(newMask);
            qtyNeeded--;
        }

        //start with all of them, flag them all as bad -- will then step through and fix
        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 RMA_Items
                             {
                                 DatetimeCreated = Convert.ToDateTime(line.DatetimeCreated),
                                 UniqueIdNo = rma.UniqueIdNo,
                                 RmaNumber = line.RmaNumber,
                                 RmaOriginalUniqueId = Convert.ToDecimal(line.RmaOriginalUniqueId),
                                 ItemSequenceNo = Convert.ToDecimal(line.ItemSequenceNo),
                                 ItemNumber = line.ItemNumber,
                                 goodRMA_flag = false,
                                 RMA_cleanedUp = line.RmaNumber.Substring(line.RmaNumber.IndexOf("/") + 1)
                             }).ToArray();

        //convert it to a new list that we can step through
        var rmaStopsAllList = RMA_stops_all.ToList();

        //go through the new list, set the goodRMA_flag for the items that meet our criteria
        rmaStopsAllList.ForEach(x => x.goodRMA_flag =
            (masksContains.Any(masks => x.RmaNumber.Contains(masks))
             || masksStartsWith.Any(masks => x.RmaNumber.StartsWith(masks)))&&
             x.RMA_cleanedUp.Length==10);

        //flip it back into our original array
        RMA_stops_all = rmaStopsAllList.ToArray();

        //pull out the good ones
        var RMA_Stops_GoodRMA = (from R in RMA_stops_all
                    where R.goodRMA_flag == true
                    select R).ToArray();

        //pull out the bad ones
        var RMA_Stops_BadRMA = (from B in RMA_stops_all
                             where B.goodRMA_flag == false
                             select B).ToArray();

除了新课程外:

class RMA_Items
{
    public DateTime DatetimeCreated { get; set; }
    public decimal UniqueIdNo { get; set; }
    public decimal ItemSequenceNo { get; set; }
    public string RmaNumber { get; set; }
    public decimal RmaOriginalUniqueId { get; set; }
    public string ItemNumber { get; set; }
    public bool goodRMA_flag { get; set; }
    public string RMA_cleanedUp { get; set; }

}

2 个答案:

答案 0 :(得分:2)

我假设line.RmaNumber应该包含masksContains中可用的任何掩码。或者,line.RmaNumber或者应该从masksStartsWith中定义的一个掩码开始。如果符合上述任何条件,则goodRMA_flag将设置为true。希望这就是你要找的东西:

goodRMA_flag = (masksContains.Any(masks => line.RmaNumber.Contains(masks))
    || masksStartsWith.Any(masks => line.RmaNumber.StartsWith(masks)))

编辑:但是由于LINQ to SQL不允许这样做,因为line.RmaNumber直接来自SQL,我们可以在RmaNumber以后的下一步更新标志在对象中可用。

var rmaStopsAllList = RMA_stops_all.ToList();
rmaStopsAllList.Foreach(x => x.goodRMA_flag = 
    (masksContains.Any(masks => x.RmaNumber.Contains(masks))
     || masksStartsWith.Any(masks => x.RmaNumber.StartsWith(masks))));
RMA_stops_all = rmaStopsAllList.ToArray();

编辑2:还需要声明一个实际的类而不是使用匿名类型,以便以后可以将其分配(如上所示)。 goodRMA_flag应该是类中的属性,并且可以在上一步中设置为任何值。

select new SomeClass    
{
    // Other initialization here
    goodRMA_flag = false,
}).ToArray();

而不是

select new
{
    // Other initialization here
    goodRMA_flag = false,
}).ToArray();

最重要的是,请务必使用正确的数据类型为此目的添加新的类定义:

public class SomeClass
{
    public string DateTime DatetimeCreated {get; set;}
    public string UniqueIdNo {get; set;}
    public string RmaNumber {get; set;}
    public int RmaOriginalUniqueId {get; set;}
    public string ItemSequenceNo {get; set;}
    public string ItemNumber {get; set;}
    public bool goodRMA_flag {get; set;}
    public string RMA_cleanedUp {get; set;}
}

答案 1 :(得分:0)

编辑:  主要问题是这是LinqToSql,他在select语句中引用了一个本地序列。 您必须获得结果并使用本地结果创建一个新对象。

希望我没有弄错你的问题。

string data = @"<Error>
                    <Code>AccessDenied</Code>
                    <Message>Request has expired</Message>
                    <Expires>2017-03-31T14:49:56Z</Expires>
                    <ServerTime>2017-05-04T11:32:40Z</ServerTime>
                    <RequestId>...</RequestId>
                     <HostId>...</HostId>
                </Error>";

XDocument xdoc = XDocument.Parse(data);
if(xdoc.Descendants("Error").Any())
{
    var errorMessage = from lv1 in xdoc.Descendants("Error")
                select lv1.Element("Message").Value;

    Console.WriteLine(errorMessage.FirstOrDefault());
}

如您所见,只需要检查包含。

1,41和ka,实现了。