如何让linq生成我想要的sql?

时间:2009-04-27 02:33:51

标签: c# sql linq

对于我来说,提供一些精心设计的SQL集处理代码来解决各种领域模型问题是第二天性。但是,趋势是不再触摸SQL。 是否有一些模式引用或转换工具可以帮助将各种SQL模式转换为Linq语法?

我会查找代码如下代码的方法:(这有一个子查询):

SELECT * FROM orders X WHERE
(SELECT COUNT(*) FROM orders Y
WHERE Y.totalOrder > X.totalOrder) < 6

(抓住有副作用的前五名最高订单)

或者,您如何知道Linq在不使用调试器的情况下作为单个语句执行?我知道您需要遵循枚举,但我会假设只是在某处查找模式。

这是来自MSDN站点,这是他们做SQL差异的例子。我可能错了,但我不认为这会在服务器上使用set处理(我认为它在本地拉取两个集合然后取得差异,这将是非常低效的)。我可能错了,这可能是该参考文献中的一种模式。

SQL差异示例:

var differenceQuery =
(from cust in db.Customers
select cust.Country)
.Except
    (from emp in db.Employees
    select emp.Country);

由于

- 更新:

- Microsoft's 101 Linq Samples in C#是一种在模式中构造linq以生成所需SQL的更接近的方法。我会发现更多的帖子。我真的在寻找一种方法(模式或转换工具)来将SQL转换为Linq。

- 更新(来自Microsoft在Linq中的差异模式的SQL):

SELECT DISTINCT [t0].[field] AS [Field_Name]
FROM [left_table] AS [t0]
WHERE NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [right_table] AS [t1]
WHERE [t0].[field] = [t1].[field]
))

这就是我们想要的,而不是我的预期。所以,这是记忆的一种模式。

5 个答案:

答案 0 :(得分:7)

如果您使用手写SQL,则可以使用ExecuteQuery,将“row”类的类型指定为函数模板参数:

var myList = DataContext.ExecuteQuery<MyRow>(
    "select * from myview");

“row”类将列公开为公共属性。例如:

public class MyRow {
    public int Id { get; set; }
    public string Name { get; set; }
    ....
}

您可以使用更多信息来装饰列:

public class MyRow {
    ....
    [Column(Storage="NameColumn", DbType="VarChar(50)")]
    public string Name { get; set; }
    ....
}

根据我的经验,linq to sql不能生成非常好的SQL代码,并且它确实为大型数据库生成了代码。 linq to sql做得非常好,它将存储过程暴露给您的客户端。例如:

var result = DataContext.MyProcedure(a,b,c);

这允许您将SQL存储在数据库中,同时具有易于使用,自动生成的.NET包装器的好处。

要查看正在使用的确切SQL,可以使用SQL Server Profiler工具:

http://msdn.microsoft.com/en-us/library/ms187929.aspx

Linq-to-Sql Debug Visualizer:

http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx

或者您可以编写自定义代码来记录查询:

http://goneale.wordpress.com/2008/12/31/log-linq-2-sql-query-execution-to-consoledebug-window/

答案 1 :(得分:4)

这就是为什么Linq Pad首先被创建的原因。 :)它可以让你轻松地看到输出是什么。查询的结果是什么等等。最好的是它是免费的。也许不是你问题的答案,但我相信它可以帮到你。

答案 2 :(得分:2)

如果你确切知道你想要的sql,那么你应该使用ExecuteQuery

我可以想象一些方法来翻译您显示的查询,但是如果您担心“Except”可能无法翻译。

  1. 测试一下。如果它以您想要的方式工作那么很好,否则:
  2. 使用您知道将翻译的项目重写它,例如:

    db.Customers.Where(c =&gt;!db.Employees.Any(e =&gt; c.Country == e.Country));

答案 3 :(得分:2)

如果您担心生成的TSQL,那么我建议将查询形式化为存储过程或UDF,并通过数据上下文访问它们。 UDF方法具有稍微更好的元数据和可组合性(与存储过程相比) - 例如,您可以向UDF查询添加添加Where / Skip / Take等,并让它在数据库(但上次检查时,只有LINQ-to-SQL(非实体框架)支持UDF用法。)

您也可以使用ExecuteQuery,但让数据库拥有固定查询的优点。

重新找到TSQL执行的内容...使用LINQ-to-SQL,您可以将任何TextWriter(例如Console.Out)分配给DataContext.Log

答案 4 :(得分:1)

我认为最好的方法是使用存储过程。在这种情况下,您可以完全控制SQL。