Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带域聚合函数(DMin)的C参数化查询_C#_Sql_Ms Access_Ms Access 2013 - Fatal编程技术网

C# 带域聚合函数(DMin)的C参数化查询

C# 带域聚合函数(DMin)的C参数化查询,c#,sql,ms-access,ms-access-2013,C#,Sql,Ms Access,Ms Access 2013,我想在一个小型C应用程序中使用以下SQL语句 SQL语句在Access 2013中运行完美 插入“收件人”对话框,侦听器 价值观 DMinid,FIGURE,char_name='Doe'和forename='John', DMinid,DIALOG,speaker=3和DIALOG_text='some text' ; 当我试着运行下面的C代码时,我得到了太少的参数异常,我检查了拼写,甚至从Access查询中复制了字符串。 在双引号中更改单引号不起作用,我得到了相同的异常。甚至可以在C语言中运

我想在一个小型C应用程序中使用以下SQL语句

SQL语句在Access 2013中运行完美

插入“收件人”对话框,侦听器 价值观 DMinid,FIGURE,char_name='Doe'和forename='John', DMinid,DIALOG,speaker=3和DIALOG_text='some text' ; 当我试着运行下面的C代码时,我得到了太少的参数异常,我检查了拼写,甚至从Access查询中复制了字符串。 在双引号中更改单引号不起作用,我得到了相同的异常。甚至可以在C语言中运行这个查询吗

其他查询工作正常

string addListeners=@INSERT INTO ADRESED_to对话,侦听器 价值观 DMin'id','FIGURE','char\u name=?而名字=?', DMin'id','DIALOG','speaker=?和对话框_text=?' ; ; foreach字符侦听器在d.u中寻址到 { 使用OleDbCommand cmd=新的OleDbCommandaddListeners,dbConn { cmd.Parameters.AddWithValue?,listener.name; cmd.Parameters.AddWithValue?,listener.forename; cmd.Parameters.AddWithValue?,speakerID; cmd.Parameters.AddWithValue?,d.dialog\u文本; cmd.ExecuteNonQuery; } } 按建议将字符串更改为以下内容无效:

@插入“收件人”对话框,侦听器 价值观 DMinid,FIGURE,char\u name=?而名字=?, DMinid,DIALOG,speaker=?和dialog_text=? ; ; 例外情况:

中发生类型为“System.Data.OleDb.OLEDBEException”的异常 System.Data.dll,但未在用户代码中处理 其他信息:参数太少。预期2


我认为这不会像你希望的那样起作用。为了有效地测试这一点,您需要access在access中测试查询时提示您输入参数

所以我可以运行这个

INSERT INTO adressed_to (dialog,listener)
VALUES (
    DMin("id", "FIGURE", "char_name='" & pchar_name& "' AND forename='" & pforename & "'"),
    DMin("id", "DIALOG", "speaker="& pSpeaker & " AND dialog_text='" & pDialog_text & "'")
);
并获得弹出窗口,这意味着当您通过OLEDB连接时,参数也将是预期的

这里的缺点是,您基本上是在生成动态SQL,而不是真正的参数化查询。虽然我希望它是可以的,因为Access一次只处理一个查询。i、 在这里你不会做太多的SQL注入,因为ACE会抛出一个异常

但是Heinzi是对的,D*功能在Access之外不可用,即直接连接到ACE时,就像通过OleDb一样。这些是VBA函数,不在ACE的上下文中。您可以将查询编写为直接SQL

INSERT INTO adressed_to (dialog,listener)
Select (select min(id) from Figure where  char_name= pchar_name AND forename= pforename)
    , (Select min(id) from DIALOG where speaker= pSpeaker AND dialog_text=pDialog_text) T

所发生的事情是,在每次迭代时,您都要不断地向这个命令对象添加参数,这是一个问题,您应该在循环之前只添加一次参数,然后在循环中为它指定一个不同的值

string addListeners = @"INSERT INTO adressed_to (dialog,listener)
VALUES (
    DMin('id', 'FIGURE', char_name =@CharName AND forename =@Forename),
    DMin('id', 'DIALOG', speaker=@Speacker AND dialog_text=@DialogText)
); ";

using (OleDbCommand cmd = new OleDbCommand(addListeners, dbConn))
{
    cmd.Parameters.Add("@CharName", SqlDbType.VarChar);
    cmd.Parameters.Add("@Forename", SqlDbType.VarChar);
    cmd.Parameters.Add("@Speacker", SqlDbType.VarChar);
    cmd.Parameters.Add("@DialogText", SqlDbType.VarChar);

    foreach (Character listener in d.addressed_to)
    {
        cmd.Parameters["@CharName"].Value = listener.name; 
        cmd.Parameters["@Forename"].Value = listener.forename; 
        cmd.Parameters["@Speacker"].Value = speakerID; 
        cmd.Parameters["@DialogText"].Value = d.dialog_text; 
        cmd.ExecuteNonQuery();
    }
}
附言:
注意:我不确定何时可以使用命名占位符或不使用Oledbcommand,但你应该明白我的观点,我认为你不能这样做

是的,OLE DB支持命名参数。但是,这些参数只能在预期值的情况下使用,而不能在值内使用。让我用一个例子来说明我的意思:

这是可行的:从myTable中选择a,其中b=

这不是:从myTable中选择a,其中b='X?Y'

在第一个例子中?用作值的占位符。在第二个例子中?是字符串中的文字问号

您所做的与第二个示例相匹配:

INSERT INTO adressed_to (dialog)
VALUES (
    SomeMethod("foo", "bar", "foobar ? baz"),
);
OLE DB不知道DMin是Access数据库的一个特殊函数,它提供了某种动态SQL功能。它所看到的是,您正在使用一个内部带有问号的字符串文字。因此,问号没有特殊意义

就我个人而言,我会尝试将插入内容改写为。。。价值观插入到。。。选择语句,该语句使用标准SQL聚合方法,而不是访问特定的域聚合函数


如果所有其他操作都失败,并且您决定使用字符串连接而不是参数:请执行适当的转义和输入操作,以避免SQL注入。

这看起来很难看,但使用Provider=Microsoft.ACE.OLEDB.12.0对我来说是可行的:

字符串addListeners= @插入“收件人”对话框,侦听器 价值观 DMin'id','FIGURE','char_name='&?&'而名字='&?&', DMin'id'、'DIALOG'、'speaker='和?&'和对话框_text='&?&'' ; ; 使用var cmd=新的OleDbCommandaddListeners、dbConn { cmd.Parameters.Add?,OleDbType.VarWChar,255.Value=Doe; cmd.Parameters.Add?,OleDbType.VarWChar,255.Value=John; cmd.Parameters.Add?,OleDbType.Integer.Value=3; cmd.Parameters.Add?,OleDbType.VarWChar,255.Value=一些文本; cmd.ExecuteNonQuery; } 它也适用于

cmd.Parameters.Add?,OleDbType.VarWChar,255.Value=O'Reilly;
但是,如果文本参数值包含单独的双引号,则会失败:

您可以避免DMin的报价挑战和注射风险, 通过从插入切换。。。插入的值。。。SELECT语句

插入“收件人”对话框,侦听器 选择 MinFIGURE.id作为对话框, 选择Minid 从对话框 其中演讲者=[p1]和对话文本=[p2] 作为听众 从数字 其中FIGURE.char_name=[p3]和FIGURE.forename=[p4];
我使用[p1]到[p4]作为参数名,以指示订单访问将期望接收参数值。在您的查询版本中,您可以替换?对于每个参数名称。

您使用的是“而不是addListeners”。尝试使用@。。。id,…,double是每次使用@I将循环放在using语句之前创建新命令时的转义方法,但异常保持不变。@SandroKoch什么是exeption,噢,我想我知道为什么,在params@SandroKoch看我的编辑,去掉引号,它就会起作用。我担心会打击你的信心,但仅仅去掉引号并没有起作用。DMin函数需要引号来确定参数。啊,是的,我忘记了D*函数在过去是不可用的oledb@Brad-我不知道,DMin和Microsoft.ACE.OLEDB.12.0在一起。@GordThompson我对此有点惊讶。为什么不能像更改之前那样使用数据宏中的D*函数?我认为它们不必在Access中运行,这就是它们功能有限的原因?@Brad-我不能肯定,但我得到的印象是,事件驱动数据宏的限制可能超出了技术上可能的范围。可能存在与性能相关的限制,或者可能会施加一些限制,以使它们更好地与Sharepoint集成。从安全角度来看,这可能是迄今为止最丑陋但最节省的解决方案:我会用它,双引号可以被截取。谢谢你。@SandroKoch当我在你的文档中建议DMin时,我不知道它会变成c中的参数查询。对不起!我想插入。。。这里的选择应该更容易。是的,这是好东西。我刚刚用C测试了它,它工作了,甚至对于包含双引号的参数值也是如此。。。VALUES语句,Access投诉查询输入必须至少包含一个表或查询。在这种情况下,这似乎不是最好的信息,但可能只是访问变得混乱-您应该能够在任何Access查询中使用域聚合函数,无论它是在Access会话中运行,还是从外部运行并连接OleDb或ODBC。@HansUp是的,您是对的。但是,如果您将VALUES部分去掉,而使用常规的select语句,它就可以正常工作。请参阅my,了解我对域聚合函数工作原理感到困惑的原因。当我在您的答案中测试上一个查询的最新版本时,Access查询输入必须再次包含至少一个表或查询,并且在这种情况下,我觉得投诉更合理。如果在末尾使用Dual,它将起作用,Dual是任何只返回一行的表或查询的占位符。我的答案有点类似,但不需要额外的表或查询。