哪个 ORM 支持这个

2024-04-12

我有一个可选的查询部分,需要在特定条件下执行。这是示例代码:

int cat = 1;
int UserID = 12;
string qry = "select * from articles";
if(cat > 0)
     qry += " where categoryID = " + cat;
if(UserID > 0)
     qry += " AND userid = " + UserID;  //The AND may be a WHERE if first condition is false

正如您所看到的,我在查询中有一个 if 语句。我目前正在使用实体框架,它不支持这种情况。有 ORM 支持吗?

Edit我试图模拟这个查询。但我有大约 20 个“IF”语句,而且查询很长。

我正在研究的 ORM 是:

  • NHibernate
  • LLBLGen
  • Subsonic

我对任何 ORM 持开放态度。谢谢


正如这里已经提到的,LINQ 允许通过简单地添加更多条件来扩展任何查询。

var query = 
  from x in xs 
  where x==1
  select x;

if (mustAddCriteria1)
  query = 
    from x in query 
    where ... // criteria 1
    select x;

if (mustAddCriteria2)
  query = 
    from x in query 
    where ... // criteria 2
    select x;

等等。这种方法效果非常好。但您可能知道 LINQ 查询的编译非常昂贵:例如实体框架每秒只能编译大约 500 个相对简单的查询(参见例如ORMBattle.NET http://ormbattle.net/).

另一方面,许多 ORM 工具支持编译查询:

  • 你通过一个IQueryable以某些为例Compile方法,并获取一个委托,允许稍后更快地执行它,因为在这种情况下不会发生重新编译。

但如果我们尝试在这里使用这种方法,我们会立即注意到我们的查询实际上是动态的:IQueryable我们每次执行的操作都可能与前一次不同。查询部分的存在由外部参数的值确定。

那么我们可以执行这样的查询吗?显式缓存?

DataObjects.Net 4 支持所谓的“布尔分支”功能。这意味着在查询编译期间对任何常量布尔表达式进行求值,并将其实际值作为真正的布尔常量注入到 SQL 查询中(即不是作为参数值或作为使用参数的表达式)。

此功能允许根据此类布尔表达式的值轻松生成不同的查询计划。例如。这段代码:

  int all = new Random().Next(2);
  var query = 
    from c in Query<Customer>.All
    where all!=0 || c.Id=="ALFKI"
    select c;

将使用两个不同的 SQL 查询执行,因此 - 两个不同的查询计划:

  • 基于索引查找的查询计划(相当快),if all==0
  • 基于索引扫描的查询计划(相当慢),if all!=0

当all==null时的情况,SQL查询:

SELECT
  [a].[CustomerId],
  111 AS [TypeId] ,
  [a].[CompanyName]
FROM
  [dbo].[Customers] [a]
WHERE(( CAST( 0 AS bit ) <> 0 ) OR( [a].[CustomerId] = 'ALFKI' ) );

当all==null时的情况,查询计划:

|--Compute Scalar(DEFINE:([Expr1002]=(111)))
   |--Clustered Index Seek(OBJECT:([DO40-Tests].[dbo].[Customers].[PK_Customer] AS [a]), SEEK:([a].[CustomerId]=N'ALFKI') ORDERED FORWARD)

第二种情况(当all!=null时),SQL查询:

SELECT
  [a].[CustomerId],
  111 AS [TypeId] ,
  [a].[CompanyName]
FROM
  [dbo].[Customers] [a]
WHERE(( CAST( 1 AS bit ) <> 0 ) OR( [a].[CustomerId] = 'ALFKI' ) );
-- Notice the ^ value is changed!

第二种情况(当all!=null时),查询计划:

|--Compute Scalar(DEFINE:([Expr1002]=(111)))
   |--Clustered Index Scan(OBJECT:([DO40-Tests].[dbo].[Customers].[PK_Customer] AS [a]))
-- There is index scan instead of index seek!

请注意,几乎任何其他 ORM 都会将其编译为使用整数参数的查询:

SELECT
  [a].[CustomerId],
  111 AS [TypeId] ,
  [a].[CompanyName]
FROM
  [dbo].[Customers] [a]
WHERE(( @p <> 0 ) OR ( [a].[CustomerId] = 'ALFKI' ) );
--      ^^ parameter is used here

由于 SQL Server(以及大多数数据库)为特定查询生成单一版本的查询计划,因此在这种情况下它有唯一的选择 - 生成带有索引扫描的计划:

|--Compute Scalar(DEFINE:([Expr1002]=(111)))
   |--Clustered Index Scan(OBJECT:([DO40-Tests].[dbo].[Customers].[PK_Customer] AS [a]), WHERE:(CONVERT(bit,[@p],0)<>(0) OR [DO40-Tests].[dbo].[Customers].[CustomerId] as [a].[CustomerId]=N'ALFKI'))

好的,这是对该功能有用性的“快速”解释。现在让我们回到你的案例。

布尔分支允许以非常简单的方式实现它:

var categoryId = 1;
var userId = 1;

var query = 
  from product in Query<Product>.All
  let skipCategoryCriteria = !(categoryId > 0)
  let skipUserCriteria = !(userId > 0)
  where skipCategoryCriteria ? true : product.Category.Id==categoryId
  where skipUserCriteria ? true : 
  (
    from order in Query<Order>.All
    from detail in order.OrderDetails
    where detail.Product==product
    select true
  ).Any()
  select product;

这个例子与你的不同,但它说明了这个想法。我使用不同的模型主要是为了能够测试这个(我的示例基于 om Northwind 模型)。

这个查询是:

  • 不是动态查询,因此您可以安全地将其传递给Query.Execute(...)方法让它作为编译查询执行。
  • 然而,每次执行都会产生相同的结果,就好像通过“附加”来完成一样IQueryable.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

哪个 ORM 支持这个 的相关文章

  • 更改图像颜色与透明背景

    我需要使用 c System Drawings 将透明背景上带有绿色圆圈的图像加载到位图图像中 这是最简单的部分 但是 我需要在将其添加到更大的图像之前更改圆圈的颜色 而不影响周围的透明度 就我而言 我需要将圆圈颜色更改为黄色并将其添加为太
  • 等待运算符错误

    我的代码有问题 我怎么解决这个问题 这个问题出现在await操作符中 public MyModel HttpClient client new HttpClient HttpResponseMessage response await cl
  • (SQL) 识别字段中字符串格式多次出现的位置

    我需要将叙述字段 自由文本 拆分为多行 目前的格式如下 Case Reference Narrative XXXX XX 123456 Endless Text up to 50k characters 在作为文本的叙述字段中 各个条目 当
  • .NET 中的 Class.forName() 等效项?

    动态获取对象类型然后创建它的新实例的 C 方法是什么 例如 如何在 C 中实现以下 Java 代码的结果 MyClass x MyClass Class forName classes MyChildClass newInstance Lo
  • 是否可以使用“WHERE”子句来选择SQL语句中的所有记录?

    晚上好 我很好奇是否可以在 SQL 语句中创建一个 WHERE 子句来显示所有记录 下面一些解释 随机 SQL 语句 Java JSP示例 正常情况 String SqlStatement SELECT FROM table example
  • C++ 并行任务的开销

    我有以下简单的功能 include
  • 有没有办法找到dll公开的所有函数

    我一直在寻找一种方法来获取映射到 dll 中函数名称的所有字符串 我的意思是您可以调用 GetProcAddress 的所有字符串 如果你对 dll 进行十六进制转储 符号 字符串 就在那里 但我认为必须有一个系统调用来获取这些名称 如果您
  • 如何生成可变参数包?

    给定不相关的输入是否可以生成非类型参数包 我的意思是 我想改变这一点 template
  • 用 OpenCL C 编写快速线性系统求解器

    我正在编写一个 OpenCL 内核 它将涉及求解线性系统 目前我的内核太慢了 提高线性系统部分的性能似乎是一个不错的起点 我还应该注意 我并没有尝试使我的线性求解器并行 我正在研究的问题在宏观层面上已经是令人尴尬的并行 以下是我编写的 C
  • 为什么我收到编译错误“使用已删除的函数 'std::unique_ptr ...”

    我收到一条巨大的编译错误消息 c mingw include c 6 1 0 bits predefined ops h 123 18 error use of deleted function std unique ptr lt Tp D
  • 获取查询的行号

    我有一个查询将返回一行 当表排序时 有什么方法可以找到我正在查询的行的行索引吗 我试过了rowid但当我期待第 7 行时却得到了 582 Eg CategoryID Name I9GDS720K4 CatA LPQTOR25XR CatB
  • 在 Linq 查询中使用动态列名称

    foreach Dimension dimensions in Enum GetValues typeof Dimension var r new ReferenceTable dimensions referenceItems List
  • 使用 FromBase64Transform 解码 base64 文件流

    The example https msdn microsoft com en us library system security cryptography frombase64transform 28v vs 110 29 aspx从M
  • Rx 在不同的线程上生产和消费

    我试图通过此处的示例代码来简化我的问题 我有一个生产者线程不断地输入数据 并且我尝试在批次之间添加时间延迟来对其进行批处理 以便 UI 有时间渲染它 但结果并不如预期 生产者和消费者似乎在同一个线程上 我不希望批处理缓冲区在正在生成的线程上
  • 从 AuthorizeAttribute 继承的属性不起作用

    我目前正在尝试根据用户角色在新的 ASP MVC 5 应用程序中实现安全性 目标是防止用户在没有特定角色 或更高角色 的情况下访问某些控制器或控制器方法 根据到目前为止我所读到的问题 我创建了一个继承 AuthorizeAttribute
  • 如何在 stl 模板中使用导出类 (__declspec(dllexport))?

    我正在使用导出的类 class declspec dllexport myclass private template declspec dllexport class std map
  • 调用泛型类的方法

    这是上下文 我尝试编写一个映射器来动态地将域模型对象转换为 ViewModel 对象 我遇到的问题是 当我尝试通过反射调用泛型类的方法时 出现此错误 System InvalidOperationException 无法对 Contains
  • 从数据库配置中的连接字符串中删除 SSIS 密码

    我有一个 SSIS 包 它使用 SQL 服务器中的 SSIS 配置表来检索 OLE DB 连接管理器的连接字符串属性 问题是我还需要相同的连接字符串来调用使用实体框架的程序集 我尝试访问连接管理器连接字符串属性 但 SSIS 总是删除密码
  • 打印任何类型的数组和列表的通用方法[重复]

    这个问题在这里已经有答案了 每当我调试一段涉及整数 双精度 字符串等数组或列表的代码时 有时我更喜欢打印它们 我为此所做的是为不同类型编写重载的 printArray printList 方法 for e g 我可能有这 3 种方法来打印各
  • DbContext.SaveChangesAsync 异常处理

    当搭建新的脚手架时ApiController通过 Visual Studio 2013 中的异步操作和实体框架支持 某些方法可以包装DbContext SaveChangesAsync https msdn microsoft com en

随机推荐