C# 运行MySql存储过程的最低访问级别

C# 运行MySql存储过程的最低访问级别,c#,mysql,C#,Mysql,我正在尝试设置连接到MySQL数据库8.0的.NET 4.7.1程序,以使用运行的最低权限。 NET程序正在使用MySql.Data建立连接。用户执行存储过程的最低权限通常只有execute权限。这在MySQL工作台或命令行中运行良好 运行.NET程序时,会返回以下异常: System.Data.SqlTypes.SqlNullValueException:'数据为空。无法对空值调用此方法或属性。“ 为了简单起见,我创建了一个非常小的演示程序来演示这个问题 数据库的设置: CREATE DATA

我正在尝试设置连接到MySQL数据库8.0的.NET 4.7.1程序,以使用运行的最低权限。 NET程序正在使用MySql.Data建立连接。用户执行存储过程的最低权限通常只有execute权限。这在MySQL工作台或命令行中运行良好

运行.NET程序时,会返回以下异常: System.Data.SqlTypes.SqlNullValueException:'数据为空。无法对空值调用此方法或属性。“

为了简单起见,我创建了一个非常小的演示程序来演示这个问题

数据库的设置:

CREATE DATABASE Spike;

CREATE PROCEDURE TestAccess()
BEGIN
END;

CREATE USER Spike@localhost IDENTIFIED WITH mysql_native_password BY 'sample';

GRANT EXECUTE ON PROCEDURE `TestAccess` TO Spike@localhost;
设置程序代码:

static void Main(string[] args)
{
    using (MySqlConnection conn = new MySqlConnection("Server=localhost;Database=Spike;uid=Spike;pwd=sample"))
    {
        conn.Open();
        Console.WriteLine("Connection open");
        MySqlCommand cmd = new MySqlCommand();
        cmd.Connection = conn;
        cmd.CommandText = "TestAccess";
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.ExecuteNonQuery();

        Console.WriteLine("Query executed");
    }
    Console.ReadKey();
}
崩溃发生在
cmd.ExecuteNonQuery()行
崩溃中的堆栈很有趣,因为它似乎表明查询了信息\u模式。记录所有语句时,我可以看到异常之前的最后一条语句是:

SELECT * FROM information_schema.routines WHERE 1=1 AND routine_schema LIKE 'Spike' AND routine_name LIKE 'TestAccess'
我不能在信息模式上授予不同的权限,但我可以在存储过程上授予更多的权限,以使更多的信息在例程表中可见,但这感觉是错误的。授予CREATE和ALTER访问权限的简单测试也不起作用


我还能做些什么,而不必给予太多的特权吗?

我找到了一个我非常满意的答案。它通过添加CheckParameters=false来更改连接字符串:

using (MySqlConnection conn = new MySqlConnection("Server=localhost;Database=Spike;uid=Spike;pwd=sample;CheckParameters=false"))

这将禁用参数检查,从而禁用信息模式查询。

这似乎是Connector/NET中的一个错误,类似于,但略有不同。当它试图确定过程的参数元数据时,它首先创建一个名为
Procedures
MySqlSchemaCollection
,其中包含有关该过程的所有元数据。(这是您在日志中看到的
SELECT*FROM information\u schema.routines,其中1=1,例程\u schema如'Spike'和例程\u name如'TestAccess'
查询。)

Spike
用户帐户没有读取
ROUTINE\u定义
列的权限,因此它是
NULL
。Connector/NET期望此字段为非NULL,并在尝试读取它时抛出
SqlNullValueException
异常

有两种解决办法:

1) 您发现的第一个方法是在连接字符串中设置
CheckParameters=False
。这将禁用对存储过程元数据的检索(避免崩溃),但如果您没有正确获取参数的顺序和类型,则调用其他存储过程可能会导致更难调试的问题。(Connector/NET无法再使用元数据为您映射它们。)


2) 切换到其他没有此错误的ADO.NET MySQL库:on。它与Connector/NET高度兼容,执行速度更快,并修复了许多问题。

进一步调查后,在这种情况下,似乎只有例程定义列为空,而使用root查看信息架构时,此列将被填充。可能相关: