我有一本字典(Dictionary dic);关键和价值动态变化。
如何使用Insert命令向SQL Server添加记录取决于dic的内容?
例如:
if dic={{"KeyA", "ValueA"}}
然后执行Insert into tblTest(KeyA) values(ValueA)
if dic={{"KeyA", "ValueA"}, {"KeyX", "ValueX"}}
然后执行Insert into tblTest(KeyA,KeyX) values(ValueA,ValueX)
if dic={{"KeyA", "ValueA"}, {"KeyC", "ValueC"}, {"KeyX", "ValueX"}}
然后执行Insert into tblTest(KeyA,KeyC,KeyX) values(ValueA,ValueC,ValueX)
依旧......
有没有人有好主意?
答案 0 :(得分:2)
你有几个选择。
假设您可以使用原始SQL,那么您可以构建一个Dynamic-SQL字符串 - 虽然您可以参数化值,但您无法参数化数据库对象名称(例如列名称),因此存在SQL注入的风险在那里 - 但是使用转义字符'['
和']'
包围所有标识符可以缓解此问题。
但是,幸运的是,值本身仍然可以参数化 - 只需动态添加参数。
我会从你的字典中生成我自己的列名列表,以构建INSERT
列表,然后相应地设置参数:
我将如何做到这一点:
var safeNames = dict.Select( pair =>
new {
ColumnName = pair.Key.Replace("[", "").Replace("]", ""), // assuming this is sufficient to prevent injection
Value = pair.Value
}
);
StringBuilder sb = new StringBuilder("INSERT INTO [table] (");
Boolean first = true;
foreach( var pair in safeNames ) {
if( !first ) sb.Append(", ");
first = false;
sb.Append("[");
sb.Append( pair.ColumnName );
sb.Append("]");
}
sb.Append( " ) VALUES ( " );
first = false;
foreach( var pair in safeNames ) {
if( !first ) sb.Append(", ");
first = false;
sb.Append("@");
sb.Append( pair.ColumnName );
}
sb.Append( ");" );
using( SqlCommand cmd = connection.CreateCommand() ) {
cmd.CommandText = sb.ToString();
foreach( var pair in safeNames ) {
cmd.Parameters.Add( '@' + pair.ColumnName ).Value = pair.Value;
}
cmd.ExecuteNonQuery();
}
如果您正在使用实体框架,则可以使用分离的实体来执行INSERT
,但请注意,您不能轻松地选择性地排除列 - 默认情况下,实体框架将始终包含所有INSERT
中的实体成员,因此如果您的列具有非NULL
默认值,否则在新的分离的Entity对象中未定义,那么它们将以NULL
值保存,因此覆盖非NULL
默认值,因此会被警告:
MyEntity detached = new MyEntity();
Type entityType = typeof(MyEntity);
IEnumerable<PropertyInfo> properties = entityType
.GetProperties()
// Exclude inherited and special properties:
.Where( pi => pi.DeclaringType == entityType && !pi.IsSpecialName )
// Exclude non-read/write properties:
.Where( pi => pi.CanRead && pi.CanWrite )
// Exclude non-scalar properties:
.Where( pi => pi.PropertyType.IsPrimitive || pi.PropertyType == typeof(String) );
foreach( PropertyInfo property in properties ) {
Object value;
if( dict.TryGetValue( property.Name, out value ) ) {
property.SetValue( detached, value );
}
}
MyDBContext dbContext = ...
// Attach the entity:
dbContext.TableName.Add( detached );
// Execute the INSERT:
dbContext.SaveChanges();
如果要从操作中排除某些列,则需要使用dbContext.Entry( $entity ).Property( e = e.PropertyName ).IsModified = false
方法(虽然我不知道这是否适用于INSERT
操作或仅UPDATE
)。