我正在处理一种内部 ORM,它使用 objects 生成参数。由于null 时它们本质上是无类型的,因此很难区分各种 SQL 空类型。
DBNull.Value 几乎适用于所有 SQL 类型,但对于我正在使用的 varbinary(max) 列却失败了。相反,你必须使用SqlBinary.Null——不要问我为什么。
我决定在这里使用一个特殊的标记值来指示何时应该使用这种列类型。完整,除了我们下面的“ORM”:
using System.Data.SqlTypes;
class MyModelType
{
public Guid ID { get; set; }
public byte[] Data { get; set; }
}
static readonly object NullSqlBinary = new object();
object SqlValueForObject(object val)
{
if (val == null)
{
val = DBNull.Value;
}
else if (val == NullSqlBinary)
{
val = SqlBinary.Null;
}
return val;
}
IDictionary<string, object> Params(MyModelType x)
{
return new Dictionary<string, object>
{
{ "@ID", x.ID },
{ "@Data", x.Data ?? NullSqlBinary },
};
}
private SqlCommand CreateCommand()
{
var cmd = Connection.CreateCommand();
cmd.CommandTimeout = 60;
return cmd;
}
SqlCommand CreateCommand(string sql, IDictionary<string, object> values)
{
var cmd = CreateCommand();
cmd.CommandText = sql;
cmd.Transaction = GetCurrentTransaction();
cmd.Parameters.Clear();
if (values != null)
{
foreach (var kvp in values)
{
object sqlVal = SqlValueForObject(kvp.Value);
cmd.Parameters.AddWithValue(kvp.Key, sqlVal);
}
}
return cmd;
}
int Execute(string sql, IDictionary<string, object> values)
{
using (var cmd = CreateCommand(sql, values))
{
return cmd.ExecuteNonQuery();
}
}
void InsertMyModel(MyModelType obj)
{
DB.Execute(
@"INSERT INTO MyTable (ID, Data)
VALUES (@ID, @Data)", Params(obj));
}