使用以下逻辑,单个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);
}
答案 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);
麦克