簡體   English   中英

我如何將其編寫為單個LINQ查詢?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM