【问题标题】:Is there a better way to code this LINQ fragment?有没有更好的方法来编码这个 LINQ 片段?
【发布时间】:2009-03-10 14:41:49
【问题描述】:

我有这段代码:

SmsDataClassesDataContext dc = new SmsDataClassesDataContext();

        // Get the customer
        Customer currentCustomer = dc.Customers.Single( c => c.Hash1 == forThisHash );


        // Get from Name (LINQ to XML) 
        var q = from c in thisSmsPack.Descendants("from")
                select c;

        string from = q.First().Value;

        foreach ( XElement element in thisSmsPack.Descendants("to") )
        {
            // Create the queue
            SmsQueue sq = new SmsQueue();
            sq.CustomerId = currentCustomer.CustomerId;
            sq.MsgFrom = from;

            sq.MsgTo = element.Attribute("name").Value;
            sq.MsgPhone = element.Attribute("phone").Value;
            sq.MsgBody = element.Attribute("msg").Value;
            sq.Priority = currentCustomer.SendsSmsAtPriority;
            sq.DontSendUntil = GetNextSendDate();

             // sq.TimeCreated = System.DateTime.Now;

            currentCustomer.SmsQueues.Add(sq);
        }
        dc.SubmitChanges();

我正在创建“SmsQueues”的新实例,填充值,当 foreach 循环完成时,我提交更改。鉴于 .NET 3.5 具有新的 lambda/linq/anonymous 类型,是否有更“现代”的方式来完成上述任务?

作为一个可能相关的附带问题,我可以在 linq 表达式的选择部分返回由不同列组成的现有类型吗?

假设你有三个表:

T1 == T1.Id, T1.Name

T2 == T2.Id, T2.Phone

T3 == T3.Name, T3.Phone, T3.SomethingElse

我可以执行一个返回的 LINQ 查询吗:

T1.Name、T2.Phone、SomethingElseNew

然后让 .NET 知道它属于 T3 类型(并且它是它的新实例)? 这样当我 SubmitChanges 时,新的 T3 实例会插入到数据库中?

我不知道我是否说清楚了:S

【问题讨论】:

    标签: linq .net-3.5


    【解决方案1】:

    我没有可用的系统来测试这个,但我认为这个(或非常接近的)应该可以工作。

    CustomerId = currentCustomer.CustomerId;
    var sqrange = from element in thisSmsPack.Descendants("to") )
                  select new SmsQueue
                  {
                 // Create the queue
                    MsgFrom = from,
                    MsgTo = element.Attribute("name").Value,
                    MsgPhone = element.Attribute("phone").Value,
                    MsgBody = element.Attribute("msg").Value,
                    Priority = currentCustomer.SendsSmsAtPriority,
                    DontSendUntil = GetNextSendDate()
                 // TimeCreated = System.DateTime.Now
                };
        currentCustomer.SmsQueues.AddRange(sqrange);
    

    编辑:修复了许多语法错误(如 cmets 中所述)

    【讨论】:

    • 你可能需要使用 AddRange() 而不是 Add()。
    • select new new SmsQueue 是错字吗?您的意思是:选择新的 SmsQueue 吗?每个项目后面的分号应该是逗号。也不能使用 currentCustomer.SmsQueues.Add(sq) (或 AddRange),因为“sq”不存在,我应该在那里添加什么? :(
    • 我找到了。我需要使用:currentCustomer.SmsQueues.Add(sqrange); (很明显,但仍然......);)我使用 AddRange 而不是 Add 并更改了“;”每个语句后的逗号。此外,您在选择中有两次“新”。但它奏效了。谢谢!!!
    • 在 Descendants("to") 之后还有另一个语法错误。第二个括号没有出现。 ;)
    【解决方案2】:

    你可以做这样的事情(语法可能有点不对,这里没有智能):

    var q = T1.Join(T2, t => t.Id, t2 => t2.Id)
        select new T3{Name=t.Name,Phone=t2.Phone,SomethingElseNew="Chickens"};
    

    【讨论】:

    • 谢谢,这帮助我弄清楚我需要逗号而不是分号。现在,如果我有一个 T4 并且 T3 有这个 T4 的 FK (T3.t4id),我可以做一个 T4.T3s.Add() 吗?我将如何引用新创建的 T3? q.?
    • 当在 DB 端正确设置 FK 时,LINQ 将处理它们而不需要连接,并且您将能够按照所述调用相关对象的方法。 q 将是一个 IEnumerable,因此您可以像访问任何其他集合一样访问它(foreach 循环、调用 .first() 等...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-14
    • 1970-01-01
    • 1970-01-01
    • 2012-07-19
    • 2022-12-08
    • 1970-01-01
    • 2013-08-18
    相关资源
    最近更新 更多