【发布时间】:2017-03-07 14:58:04
【问题描述】:
在我的应用程序中,我想将 GridControl 绑定到包含来自多个数据库表(用外键引用)的数据的 DataTable。
我在更新数据时遇到了问题,因为我在引用多个数据库表的命令上使用了 SqlDataAdapter。我收到错误:
不支持对多个基表进行动态 sql 生成
我试图通过创建一个视图来解决这个问题,该视图将多个表组合成一个“表”,然后我可以绑定到我的 GridControl。
插入数据是在视图上使用“代替”触发器完成的,在该视图中,我将适当的数据添加到适当的表中。在普通的 t-sql 中,插入工作完美无缺。我可以将数据插入到我的视图中,并将其插入到适当的表中。我的 SqlDataAdapter 更新应该没有问题,因为它正在更新一个“表”,其余更新由触发器完成。
不幸的是,我仍然收到错误
不支持对多个基表进行动态 sql 生成
你知道为什么 SqlDataAdapter 仍然不让我更新,即使它现在只更新一个“表” - 视图?
我的代码:
观点:
CREATE view [dbo].[v_TestTypeParameter_grid]
as
(
select t1.Id, t3.Name, t3.Description, t2.MinValue, t2.MaxValue, t4.Symbol
from TestTypes as t1 join
TestTypeParameters as t2 on t1.Id = t2.TestType join
Parameters as t3 on t2.Parameter = t3.Id left join
Units as t4 on t2.Unit = t4.Id
)
而不是在视图上触发:
CREATE TRIGGER [dbo].[tr_TestTypeParameterAdded] ON [dbo] [v_TestTypeParameter_grid]
INSTEAD OF INSERT
AS
BEGIN
DECLARE
@TestTypeId int,
@ParameterId int,
@UnitId int,
@ParameterName varchar(100),
@MinValue decimal(18,2),
@MaxValue decimal(18,2),
@UnitSymbol varchar(100)
SELECT @TestTypeId = Id, @ParameterName = Name, @MinValue = MinValue, @MaxValue = MaxValue, @UnitSymbol = Symbol FROM Inserted;
SELECT @ParameterId = Id FROM Parameters WHERE Name = @ParameterName;
SELECT @UnitId = Id from Units WHERESymbol = @UnitSymbol;
INSERT INTO TestTypeParameters(TestType, Parameter, MinValue, MaxValue, Unit) VALUES(@TestTypeId, @ParameterId, @MinValue, @MaxValue, @UnitId);
END
我的绑定代码:
mvarParameterListAdapter = DBService.GetDataAdapter("select * from v_TestTypeParameter_grid where Id = " + mvarTestTypeId);
mvarParameterTable = new DataTable();
mvarParameterListAdapter.Fill(mvarParameterTable);
gcParameters.DataSource = mvarParameterTable;
gcParameters.RefreshDataSource();
DBService.GetDataAdapter 方法:
public static SqlDataAdapter GetDataAdapter(String command, DataTable parameters = null)
{
SqlConnection lvarConnection = GetConnection();
SqlCommand lvarCommand = new SqlCommand(command, lvarConnection);
if (parameters != null && parameters.Rows.Count > 0)
{
foreach (DataRow lvarRow in parameters.Rows)
{
lvarCommand.Parameters.AddWithValue("@" + lvarRow[0], lvarRow[1]);
}
}
SqlDataAdapter lvarAdapter = new SqlDataAdapter(lvarCommand);
SqlCommandBuilder lvarCommandBuilder = new SqlCommandBuilder(lvarAdapter);
return lvarAdapter;
}
更新代码:
try
{
mvarParameterListAdapter.Update(mvarParameterTable);
}
catch (Exception ex)
{
// Here, I'm getting the error
}
在 t-sql 中工作的插入:
INSERT INTO v_TestTypeParameter_grid VALUES (2, 'Fe', 'Iron', 5.2, 7.9, '%')
由于我有几个像这样工作的 GridControl(使用不同的数据),我试图自己不为 SqlDataAdapter 生成选择、插入、更新和删除命令,而不是那样,我使用 SqlCommandBuilder 来保持它更简单。
谢谢!
编辑:
为了(希望)把事情说清楚:
这是我正在处理的 GridControl。请原谅我的列名,它们是波兰语。 身份识别器 = Id, Nazwa = 名字, Opis = 描述, 最小值 = 最小值, 马克西姆 = 最大值, Jednostka = 单位
现在,我正在向 GridControl 添加另一行,其中仅包含“Nazwa(名称)”和“Opis(描述)”字段。
我正在使用要向其中添加参数的 TestType 的 ID 填充“Identyfikator(Id)”字段,并使用其默认值填充其他字段。新行将自动添加到绑定到我的 GridControl 的 DataTable 中,并且在用户单击“保存”后,我想使用 SqlDataAdapter.Update() 方法将这些更改推送到数据库。这是我得到错误的地方:
不支持对多个基表进行动态 sql 生成
我希望它清楚地表明了我想要实现的目标以及我将如何努力做到这一点。
编辑:
我设法找到了解决这个问题的方法。您可以在下面的答案中查看。
【问题讨论】:
-
你有一个重大缺陷。您假设插入时只会插入一行。这不是 sql server 触发器的工作方式。他们每次操作开火一次。您需要将其编写为基于单个集合的插入并摆脱那些标量变量。似乎从插入到参数和单位的简单连接可以解决触发问题。您还迫切需要阅读有关参数化查询的信息。您发布的内容容易受到 sql 注入。
-
@SeanLange 我确实知道每次操作都会触发一次 sql 触发器,这是一个测试版本,我只是想看看更新是否有效,因为我花了几个小时试图找到一种方法来进行更新尽可能干净。我也知道参数化查询是什么,正如您在 GetDataAdapter 方法中看到的那样,可以使用参数,但同样,它只是一个测试版本。
-
在您的帖子中,您谈到了更新,但我在此代码中的任何地方都没有看到一条更新语句。您还提到了其他地方进行更新的其他触发器。当我们没有所有信息时,真的很难提供帮助。您能否发布更多详细信息,以便我们查看问题所在?
-
@SeanLange 我说的是 SqlDataAdapter 更新,您可以在“更新代码:”部分的第 3 行看到。我想在用户编辑绑定到 GridControl 的 mvarParameterTable 后更新 v_TestTypeParameter_grid 视图。我想专注于至少插入添加到 DataTable 的数据才能工作。在我可以处理插入数据之后,我将以相同的方式更新和删除它。我将在一分钟内编辑我的帖子,以展示我如何显示数据以及我想如何编辑它。希望它能把事情弄清楚。
标签: c# sql-server database sqldataadapter gridcontrol