[英]How would I write this as a single LINQ query?
使用以下邏輯,單個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);
}
我建議,如果僅在一個地方需要這樣做,那么您現在所擁有的就相當清楚了,應該保留下來。
如果您經常這樣做,請執行以下操作:
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查詢,也可以接受這可能實際上需要由存儲過程完成。
我非常確定您可以使用一個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
)
);
很好,不是嗎? :DI仍然建議不要使用它。 第一種情況很簡單-如果商品具有正確的ID,並且不是Service類型,則我們有一個匹配項。
第二種情況比較棘手。 我們必須檢查該項目是否具有具有提供的ID的項目的ParentID屬性中的ID,但前提是具有提供的ID的項目的類型為Service。 因為我們不知道是否有與所提供的ID,當我們檢查這種類型的服務項目時,首先要檢查有Any()
如果有這樣的項目,依靠的條件評估and
。
var t = ctx.BranchInfos.Single(
p => (p.BranchID == branchId && p.Type != BranchType.Service.ToString) ||
(p.BranchID == GetBranchParentId(branchId) && p.Type == BranchType.Service.ToString));
其中GetBranchParentId是一個函數,該函數返回ID作為參數傳遞的分支的BranchId。
但是,我喜歡您的原始代碼,因此不會使用單個查詢來獲取數據。
除非我弄亂了邏輯,否則這可能會為您提供所需的東西。
編輯:不同的方法
var t = ctx.BranchInfos.Where(p.BranchID == branchId).First(p => p.Type == BranchType.Service.ToString() ? p.Parent : p);
這可能會起作用,但是有點尷尬。
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();
我相信以下內容等同於您的代碼示例。 我添加了一些模擬代碼,以將其變成一個獨立的示例。
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
}
}
}
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獲取我的分支)或(如果分支類型為Service,則使我知道子ID的分支的父節點,讓我知道)
也:
即使其中有一個子查詢,它也會對數據庫產生一次命中,因為您在子查詢中使用了相同的Datacontext。
提供的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();
我認為您可以執行以下操作:
var t = ctx.BranchInfos.FirstOrDefault(p => p.BranchID == branchId || p.BranchID == t.Parent);
麥克風
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.