簡體   English   中英

將SQL轉換為LINQ以一次命中數據庫

[英]Converting SQL to LINQ to hit database once

如何將以下T-SQL查詢轉換為LINQ?

SELECT * FROM "VwBusinessUnits"
                WHERE "BusinessUnitName" in (
                    SELECT DISTINCT TOP 10 "BusinessUnitName"
                    FROM "VwBusinessUnits"
                    WHERE("StateOrProvince" = 'QLD')
                    ORDER BY "BusinessUnitName"
                )

我有這個解決方案正在工作,但是它對數據庫有兩個影響,我更喜歡上面的T-SQL查詢之一:

SqlExpression<VwBusinessUnits> distinctBusinessUnitNamesSqlExpression = db.From<VwBusinessUnits>()
                .Where(x => x.StateOrProvince.ToUpper() == "QLD")
                .OrderBy(x => x.BusinessUnitName)
                .SelectDistinct(x => x.BusinessUnitName)
                .Take(take);

            var distinctBusinessUnitNames = db.Select(distinctBusinessUnitNamesSqlExpression).Select(x => x.BusinessUnitName);

            SqlExpression<VwBusinessUnits> sqlExpression = db.From<VwBusinessUnits>()
                .Where(x => distinctBusinessUnitNames.Contains(x.BusinessUnitName));

            List<VwBusinessUnits> businessUnits = db.Select(sqlExpression);

更新:

dbSystem.Data.IDbConnection的實例,我在ServiceStack.OrmLite.OrmLiteConnectionFactoryExtensions使用擴展方法

我使用它來工作:

            string sql = @"SELECT * FROM VwBusinessUnits 
                            WHERE BusinessUnitName in 
                            (SELECT DISTINCT TOP {0} BusinessUnitName
                            FROM VwBusinessUnits 
                            WHERE(StateOrProvince = @state))";
            int take = 10;
            string state = "QLD";                
            List<VwBusinessUnits> businessUnits = db.SqlList<VwBusinessUnits(string.Format(sql, take), new { state });

由於某種原因,我無法將take作為狀態參數的@參數傳遞

@take附近的語法不正確

沒有SQL注入攻擊的風險,因為take參數是int

如果有人找到了用LINQ代替硬編碼SQL查詢的方法,請告訴我。

因此,您有一個表: VwBusinessUnits ,其中每個VwBusinessUnit至少具有屬性BusinessUnitNameStateOrProvince

las,您忘了告訴我們您的要求,但是從您的SQL語句來看,您似乎希望所有VwBusinessUnits所有屬性的名稱都按以下順序顯示:

第10個BusinessUnitNamesVwBusinessUnits ,會導致如果你將采取BusinessUnitNames所有VwBuisinessUnits有一個StateOrProvince ,等於QLDBusinessUnitName ,並責令這些名稱。

這是一種羅word的說法:

  • 收集VwBusinessUnits的集合,
  • 僅保留StateOrProvince等於QLD那些。
  • 提取BusinessUnitName
  • 順序升序
  • 拿第一個10

查詢將是這樣的:

var collectionOfNames = myDbContext.VwBusinessUnits
    .Where(vwBusinessUnit => vwBusinessUnit.Name == "QLD")
    .Select(vwBusinessUnit => vwBusinessUnitName)
    .OrderBy(name => name)
    .Take(10);

注意:您只創建了一個IQueryable對象,但尚未執行。 僅可查詢的Expression已被填充。

您的主要查詢是這樣的:

  • 我們有一系列的業務部門名稱
  • 取得所有VwBusinessUnits
  • 按業務單位名稱的順序僅保留那些具有BusinessUnitName VwBusinessUnits

該查詢類似於:

var result = myDbContext.VwBusinessUnits
    .Where(vwBusinessUnit => collectionOfNames.Contains(vwBusinessUnit.Name));

您可以將這些查詢分開放置,也可以一次查詢一次。 因為他們仍然是查詢,但這不會加快您的處理速度。 但是,它使可讀性,可測試性和可維護性較差:

var result = myDbContext.VwBusinessUnits
    .Where(vwBusinessUnit => 
        myDbContext.VwBusinessUnits
            .Where(vwBusinessUnit => vwBusinessUnit.Name == "QLD")
            .Select(vwBusinessUnit => vwBusinessUnitName)
            .OrderBy(name => name)
            .Take(10)
            .Contains(vwBusinessUnit.Name));

查詢中的問題

如果您的BusinessUnitNames不唯一,則內部查詢會出現一些問題。

假設您有大量的VwBusinnessUnits集合:數百萬個。 這些VwBusinessUnits have a name like "AAAAAAAAAA". If you would order all names of all millions十個VwBusinessUnits have a name like "AAAAAAAAAA". If you would order all names of all millions VwBusinessUnits have a name like "AAAAAAAAAA". If you would order all names of all millions VwBusinessUnit的VwBusinessUnits have a name like "AAAAAAAAAA". If you would order all names of all millions則將以10倍相同“ AAAAAAAAA”的序列結尾,就好像您只選擇了前1個

如果要確保有10個不同的名稱,即使幾個公司的名稱相同,也可以考慮在OrderByTake(10)之前使用Distinct

我會這樣寫:

var innerQuery = db.BusinessUnits
    .Where(x => x.StateOrProvince.ToUpper() == "QLD")
    .Select(x => x.BusinessUnitName)
    .Distinct()
    .OrderBy(x => x)
    .Take(take);

在這一點上,我們有一個IQueryable可以用作子查詢:

var outerQuery = db.VwBusinessUnits
    .Where(x => innerQuery.Contains(x.BusinessUnitName));
var data = outerQuery.ToList();

進行Linq查詢將對您有所幫助,

List<VwBusinessUnits> businessUnits = db.VwBusinessUnits
                                      .Where( y => (
                                                     db.VwBusinessUnits
                                                     .Where(x => x.StateOrProvince== "QLD")
                                                     .OrderBy(x => x.BusinessUnitName)                                         
                                                     .Select(x=>x.BusinessUnitName)
                                                     .Distinct()
                                                     .Take(take)
                                                   ).Contains(y.BusinessUnitName)
                                             ).ToList()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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