C# 如何安全地允许用户在SQL中定义新列的名称?

C# 如何安全地允许用户在SQL中定义新列的名称?,c#,mysql,C#,Mysql,我正在构建一个非常基本的库存管理应用程序,使用Xamarin表单构建UI,使用MySQL构建和维护数据库。我希望用户能够为每个项目定义自己的属性,以允许应用程序灵活地告诉用户有关库存的信息。我的计划是将一种类型的所有项目共享(例如,型号为0000的所有摄像头都是5mp摄像头)作为一个新列插入到所有项目的表中,对于没有该特定属性的项目(例如,冰箱没有分辨率),该列将为空 下面是如果我不关心SQL注入的威胁,我将如何完成任务 //this Dictionary would be popula

我正在构建一个非常基本的库存管理应用程序,使用Xamarin表单构建UI,使用MySQL构建和维护数据库。我希望用户能够为每个项目定义自己的属性,以允许应用程序灵活地告诉用户有关库存的信息。我的计划是将一种类型的所有项目共享(例如,型号为0000的所有摄像头都是5mp摄像头)作为一个新列插入到所有项目的表中,对于没有该特定属性的项目(例如,冰箱没有分辨率),该列将为空

下面是如果我不关心SQL注入的威胁,我将如何完成任务

    //this Dictionary would be populated by data pulled from user inputs.        
    IDictionary<string, object> userProps = new Dictionary<string, object>;

    MySQLCommand dBCommand = new MySQLCommand();

    foreach(string prop in userProps.Keys)
    {
       dbCommand.CommandText = dbCommand.CommandText + "ALTER TABLE items ADD COLUMN " + prop + " " + userProps[prop].GetType().ToString() + ";";  
    }
//此字典将由从用户输入中提取的数据填充。
IDictionary userProps=新字典;
MySQLCommand dBCommand=新的MySQLCommand();
foreach(userProps.Keys中的字符串prop)
{
dbCommand.CommandText=dbCommand.CommandText+“更改表项添加列”+prop+“”+userProps[prop].GetType().ToString()+“;”;
}

然后当然打开一个连接并执行该语句。我知道我可以用SQLParameter类的实例替换userProps[prop].GetType().ToString(),但它似乎没有适合列或表名的数据类型(这对于具有变量值(如MAC地址)的属性很重要)。我希望我是个傻瓜,有一种简单的方法可以在不将应用程序暴露于SQL注入的情况下实现这一点。如果没有,我愿意接受关于更密集解决方案的建议。非常感谢所有花时间阅读本文并提供帮助的人。

一种常见的方法是创建一个
属性表
PropertyId
Property
),并允许用户定义新属性。类似于
ItemProperties
ItemId
PropertyId
PropertyValue
)的表格允许用户将属性与项目关联。SQL注入不是问题。有用的查询可能会变得相当麻烦,例如,查找属性为color=red、size=8.5的所有鞋子。当属性具有不同的类型、范围和其他属性时,问题也越来越严重。OTOH,它避免了一大堆不适用于大多数行的列。用户必须永远拥有DDL权限。@HABO这会使查询变得有点乏味,但我想如果这是唯一安全的方法,那么它必须是这样的。我并不担心大部分的空值,因为我预计程序的规模不会达到问题的程度,至少在很长一段时间内不会。我的另一个想法是只检查为属性名称指定的字符串是否有问题字符,如“;”,“=”,或者在用户输入数据时使用“-”,但我不知道这有多安全。在SQL Server中,它提供了一种处理讨厌的名称的方法,例如使用空格或不寻常的字符。我不知道是否有类似的mysql。允许用户添加属性是一个永无止境的挑战。您允许哪些数据类型?如何实现约束?(
SellBy
必须是将来的日期,但不得超过2周。)假复制品?(
Width
鞋的宽度与墙纸的宽度不同。)有效值列表,例如t恤尺寸?简短回答:我不知道,我是SQL Server的走狗。试图清理用户提供的对象名称总是充满了机会,通常是反对者。要想成功,必须在任何地方都做到完美。不仅是
alter表
,还有对列的每个引用。反勾号似乎会破坏可执行文件,例如
select/*!version()*/
。还潜伏着什么?