![](/img/trans.png)
[英]In Linq-to-SQL, does IMultipleResults hit the database more than once?
[英]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);
更新:
db
是System.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
至少具有屬性BusinessUnitName
和StateOrProvince
las,您忘了告訴我們您的要求,但是從您的SQL語句來看,您似乎希望所有VwBusinessUnits
所有屬性的名稱都按以下順序顯示:
第10個
BusinessUnitNames
的VwBusinessUnits
,會導致如果你將采取BusinessUnitNames
所有VwBuisinessUnits
有一個StateOrProvince
,等於QLD
由BusinessUnitName
,並責令這些名稱。
這是一種羅word的說法:
VwBusinessUnits
的集合, StateOrProvince
等於QLD
那些。 BusinessUnitName
查詢將是這樣的:
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個不同的名稱,即使幾個公司的名稱相同,也可以考慮在OrderBy
和Take(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.