我是销售ASP.NET MVC3应用程序的公司的SQL Server DBA,该应用程序使用LINQ和Entity Framework 4进行所有数据库访问.当我在我的SQL Server的计划缓存中找到由LINQ生成的低效查询时,我希望能够在源代码中找到LINQ语句,以便我可以对其进行优化.找到生成给定SQL语句的LINQ的最佳方法是什么?
例如,有没有办法在配置文件中放置一个条目或以某种方式装饰代码,以便类和方法名称或LINQ语句本身作为注释包含在生成的SQL中?
假设我有三个表,[ONE],[ONE_TWO]和[TWO].[ONE_TWO]是一个多对多连接表,只有[ONE_ID和[TWO_ID]列.设置了外键以将[ONE]链接到[ONE_TWO]和[TWO]到[ONE_TWO].FK使用ON DELETE CASCADE选项,以便在删除[ONE]或[TWO]记录时,相关的[ONE_TWO]记录也将自动删除.
我希望在[TWO]表上有一个触发器,这样当删除[TWO]记录时,它会执行一个存储过程,该过程以[ONE_ID]作为参数,传递链接到[ONE_ID]的[ONE_ID]值.发生删除前的TWO_ID]:
DECLARE @Statement NVARCHAR(max)
SET @Statement = ''
SELECT @Statement = @Statement + N'EXEC [MyProc] ''' + CAST([one_two].[one_id] AS VARCHAR(36)) + '''; '
FROM deleted
JOIN [one_two] ON deleted.[two_id] = [one_two].[two_id]
EXEC (@Statement)
Run Code Online (Sandbox Code Playgroud)
显然,我需要一个BEFORE DELETE触发器,但在SQL Server 2005中没有这样的东西.由于级联FK,我无法使用INSTEAD OF触发器.
我得到的印象是,如果我使用FOR DELETE触发器,当我将[deleted]连接到[ONE_TWO]以查找[ONE_ID]值的列表时,FK级联将已经删除了相关的[ONE_TWO]记录,所以我永远不会找到任何[ONE_ID]值.这是真的?如果是这样,我怎样才能实现我的目标?
我想我需要将FK加入[TWO]改为[ONE_TWO]以不使用级联并在我手动删除[TWO]记录之前在触发器中手动从[ONE_TWO]进行删除.但如果有更简单的方法,我宁愿不经历所有这些.
我遇到动态SQL问题,并将我的代码减少到这个最简单的例子.为什么这样:
DECLARE @Statement NVARCHAR(1000), @Name SYSNAME;
SET @Statement = N'SELECT TOP 1 @Name = name from sys.objects';
EXEC sp_execute @Statement, N'@Name SYSNAME OUTPUT', @Name OUTPUT;
Run Code Online (Sandbox Code Playgroud)
告诉我这个:
Msg 214, Level 16, State 2, Procedure sp_execute, Line 1
Procedure expects parameter '@handle' of type 'int'.
Run Code Online (Sandbox Code Playgroud)
什么是正确的语法?
我也尝试过:
DECLARE @Statement NVARCHAR(1000), @Name SYSNAME;
SET @Statement = N'SELECT TOP 1 @NameOUT = name from sys.objects';
EXEC sp_execute @Statement, N'@NameOUT SYSNAME OUTPUT', @NameOUT = @Name OUTPUT;
Run Code Online (Sandbox Code Playgroud)
但是有同样的错误.
我有一个表格,其中包含可以成为账单一部分的记录.我可以知道哪些已经是账单的一部分,因为该表有一个BillId列,当发生这种情况时,它会被应用程序代码更新.我想阻止更新任何具有非null BillId的记录.我认为以下内容应该照顾到:
CREATE TRIGGER [Item_Update_AnyBilled]
ON [dbo].[Item]
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @AnyBilled BIT;
SELECT TOP(1) @AnyBilled = 1
FROM inserted i
JOIN deleted d ON i.ItemId = d.ItemId
WHERE d.BillId IS NOT NULL;
IF COALESCE(@AnyBilled, 0) = 1 BEGIN
RAISERROR(2870486, 16, 1); -- Cannot update a record that is part of a bill.
ROLLBACK TRANSACTION;
END;
END;
Run Code Online (Sandbox Code Playgroud)
然而,还有一个皱纹.Item表还有一个DATETIME Modified列,以及一个更新它的触发器.
CREATE TRIGGER [dbo].Item_Update_Modified
ON [dbo].[Item]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE a
SET Modified = …Run Code Online (Sandbox Code Playgroud)