我如何将其作为单个LINQ查询编写?

时间:2009-04-21 23:30:27

标签: c# .net linq .net-3.5

使用以下逻辑,单个LINQ查询的正确语法是什么?

  

If Branch is Service, I want its parent, otherwise I want Branch.

你可以批评我的尝试并告诉我如何改进它吗?

int branchId = 21;
var t = ctx.BranchInfos.Single(p => p.BranchID == branchId );
if (t.Type == BranchType.Service.ToString())
{
    t = ctx.BranchInfos.Single(p => p.BranchID == t.Parent);
}

9 个答案:

答案 0 :(得分:2)

我建议如果只在一个地方需要这个,那么你现在拥有的东西是相当清楚的,应该保留。

如果你这么做很多,那就做点什么:

public static BranchInfo BranchOrServiceParent(
    this IEnumerable<BranchInfo> input)
{ 
    var t = BranchInfos.Single(p => p.BranchID == branchId);
    if (t.Type == BranchType.Service.ToString())    
        t = input.BranchInfos.Single(p => p.BranchID == t.Parent);
    return t;
}

然后使用它就像:

int branchId = 21;
var t = ctx.BranchInfos.BranchOrServiceParent();

如果您随后需要以清晰的方式参数化/更改事物。

如果您随后发现两个可能到数据库的行程是一个性能问题,那么您可以尝试复杂的Linq查询或接受这可能需要实际由存储过程完成。

答案 1 :(得分:0)

我很确定你可以用一个LINQ语句来做到这一点,但我确信你不应该这样做。它不会提高可读性,也不会提高性能。

var t = ctx.BranchInfos.Single(x =>
  (
    x.BranchID == branchID &&
    x.Type != BranchType.Service.ToSting()
  )
  ||
  (
    ctx.BranchInfos.Any(
      y.BranchID == branchID) &&
      y.Type == BranchType.Service.ToSting()) &&
    x.BranchID == ctx.BranchInfos.Single(
      y.BranchID == branchID) &&
      y.Type == BranchType.Service.ToSting()).ParentID
  )
);
好的,不是吗? :D我仍然建议不要使用它。第一种情况很简单 - 如果项目具有正确的ID且不属于服务类型,则我们匹配。

第二种情况比较棘手。我们必须检查项目是否具有来自具有提供的ID的项目的ParentID属性的ID,但仅当具有提供的ID的项目是Service类型时。因为我们在检查时不知道是否有带有提供的ID的项目并且输入了Service,所以我们必须首先检查Any()是否有这样的项目,并依赖于{{1}的条件评估}。

答案 2 :(得分:0)

var t = ctx.BranchInfos.Single(
  p => (p.BranchID == branchId && p.Type != BranchType.Service.ToString) ||
       (p.BranchID == GetBranchParentId(branchId) && p.Type == BranchType.Service.ToString));

其中GetBranchParentId是一个函数,它返回Branch的BranchId,其id作为参数传递。

但是,我喜欢你的原始代码,因此我不会使用单个查询来获取我的数据。

答案 3 :(得分:0)

这可能会让你得到你需要的东西,除非我搞砸了逻辑。

编辑:不同的方法

var t = ctx.BranchInfos.Where(p.BranchID == branchId).First(p => p.Type == BranchType.Service.ToString() ? p.Parent : p);

答案 4 :(得分:0)

这可能会奏效,但有点尴尬。

var t = ctx.BranchInfos.Where(p => p.BranchID == branchId)
    .Select(p => 
      p.Type != BranchType.Service.ToString() 
      ? p 
      : ctx.BranchInfos.Single(t => p.Parent == t.BranchId)).FirstOrDefault();

答案 5 :(得分:0)

我相信以下内容等同于您的代码示例。我添加了一些模拟代码,将其转换为一个独立的示例。

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Context ctx = new Context();
            ctx.BranchInfos.Add(new BranchInfo() { Type = "NonService", BranchID = 20, Parent = 0 });
            ctx.BranchInfos.Add(new BranchInfo() { Type = "Service", BranchID = 21, Parent = 20 });
            ctx.BranchInfos.Add(new BranchInfo() { Type = "NonService", BranchID = 30, Parent = 20 });

            int branchId = 21;

            var t = (from a in ctx.BranchInfos
                     where a.BranchID == branchId
                     select a.Type != BranchType.Service.ToString() ? a :
                     (from b in ctx.BranchInfos
                      where b.BranchID == a.Parent
                      select b).Single()).Single();

            Console.WriteLine(t.BranchID); // Prints 20
        }

        class Context
        {
            public List<BranchInfo> BranchInfos = new List<BranchInfo>();
        }

        class BranchInfo
        {
            public string Type;
            public int BranchID;
            public int Parent;
        }

        enum BranchType
        {
            Service = 0
        }
    }
}

答案 6 :(得分:0)

var t = ctx.BranchInfos.Where(p =>
 (
   p.BranchID == branchID &&
   p.Type != BranchType.Service.ToSting()
 )
 ||
 (
   p.Type == BranchType.Service.ToSting() &&
   ctx.BranchInfos.Where(p => p.BranchID == branchID).FirstOrDefault() != null &&
   p.BranchID == ctx.BranchInfos.Where(p => p.BranchID == branchID).FirstOrDefault().ParentID
 )).FirstOrDefault();

这里的逻辑是:(如果类型是服务,请通过ID获取分支)或者(如果分支类型是服务,请告诉我分支的父级,我知道子ID)

ALSO:

即使那里有一个子查询,它也会评估为DB的单击,因为你在子查询中使用相同的Datacontext。

答案 7 :(得分:0)

如果BranchInfo.Parent与BranchInfo的类型相同:

int branchID;
var branchOrParent = db.BranchInfos
    .Where(b => b.BranchID == branchID)
    .Select(b => b.Type == BranchType.Service.ToString() ? b.Parent : b)
    .FirstOrDefault();

答案 8 :(得分:-2)

我认为你可以这样做:

var t = ctx.BranchInfos.FirstOrDefault(p =&gt; p.BranchID == branchId || p.BranchID == t.Parent);

麦克