C# 将SQL转换为LINQ以命中数据库一次
如何将以下T-SQL查询转换为LINQC# 将SQL转换为LINQ以命中数据库一次,c#,linq,tsql,
ormlite-servicestack,C#,Linq,Tsql,
ormlite Servicestack,如何将以下T-SQL查询转换为LINQ SELECT * FROM "VwBusinessUnits" WHERE "BusinessUnitName" in ( SELECT DISTINCT TOP 10 "BusinessUnitName" FROM "VwBusinessUnits" WHERE("StateOrProvince" = '
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);
出于某种原因,我无法将take作为@parameter-like-state进行传递
@take附近的语法不正确
没有SQL注入攻击的风险,因为take参数是int
如果有人在LINQ中找到了这样做的方法,而不是硬编码SQL查询,请告诉我。我会这样写: 此时,我们有一个可用作子查询的IQueryable:
以下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()
因此,您有一个表:VwBusinessUnits,其中每个VwBusinessUnit至少有属性BusinessUnitName和一个StateOrProvince
遗憾的是,您忘了告诉我们您的要求,但从SQL语句中,您似乎希望所有VwBusinessUnits的所有属性都具有以下顺序显示的名称:
VwBusinessUnits的前10个BusinessUnitName,如果您从所有VwBusinessUnits中获取BusinessUnitName,这些BusinessUnitName的state或provision等于QLD by BusinessUnitName,并对这些名称进行排序,则会产生这些名称
这是一种冗长的说法:
以VwBusinessUnits的集合为例,
仅保留状态或权限等于QLD的那些。
提取BusinessUnitName
升序
以前10个为例
对此的查询类似于:
var collectionOfNames = myDbContext.VwBusinessUnits
.Where(vwBusinessUnit => vwBusinessUnit.Name == "QLD")
.Select(vwBusinessUnit => vwBusinessUnitName)
.OrderBy(name => name)
.Take(10);
var result = myDbContext.VwBusinessUnits
.Where(vwBusinessUnit => collectionOfNames.Contains(vwBusinessUnit.Name));
注意:您只创建了一个IQueryable对象,它尚未执行。只填充了可查询的表达式
您的主查询如下所示:
我们有一系列的业务单位名称
以所有业务单位为例
在业务单元名称序列中仅保留那些具有BusinessUnitName的业务单元
查询类似于:
var collectionOfNames = myDbContext.VwBusinessUnits
.Where(vwBusinessUnit => vwBusinessUnit.Name == "QLD")
.Select(vwBusinessUnit => vwBusinessUnitName)
.OrderBy(name => name)
.Take(10);
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));
你的问题
如果businessunitname不唯一,则内部查询会出现一些问题
假设您有一个非常大的VWBusinessUnits集合:数以百万计。其中10个业务单位的名称类似AAAAA。如果您要订购所有百万VWbusinessunits的所有名称,那么您将以相同AAAAAAAAAA的10倍序列结束,这就好像您只选择了前1个名称一样
如果你想确定有10个不同的名字,即使几个公司有相同的名字,考虑在OrrdBy之前使用不同的,并且采取10
尝试列出BuffersUns= Db.ExcExtQueQuy SQL查询;GaurangDave没有ExecuteQuery方法。我能找到的最接近的东西是ExecuteSql,但它返回一个int。System.Data.Linq命名空间中有ExecuteQuery方法。我用过很多次。检查更多详细信息。@GaurangDave db是System.Data.IDbConnection的实例,不是DataContextdb.VwBusinessUnits不编译,没有名为VwBusinessUnitsdb.VwBusinessUnits的成员,db.BusinessUnits不编译,它们不是实例db的成员。db实例没有名为VwBusinessUnits的成员。您自己的代码是:来自VwBusinessUnits,因此我假设您有一个具有此名称的表。如果您不提供与数据库的接口,我们将不得不猜测标识符名称。如果您在重新解释错误猜测的标识符时遇到问题,那么在下次提问时,您应该更加注意为我们提供数据库接口。var result = myDbContext.VwBusinessUnits
.Where(vwBusinessUnit =>
myDbContext.VwBusinessUnits
.Where(vwBusinessUnit => vwBusinessUnit.Name == "QLD")
.Select(vwBusinessUnit => vwBusinessUnitName)
.OrderBy(name => name)
.Take(10)
.Contains(vwBusinessUnit.Name));