这是我对这个问题的解决方案,这几乎正是您的经理所要求的……尽管晚了 18 个月。
作为香草方法:
/// <summary>
/// Calls a given Sql function and returns a singular value
/// </summary>
/// <param name="db">Current DbContext instance</param>
/// <typeparam name="T">CLR Type</typeparam>
/// <param name="sql">Sql function</param>
/// <param name="parameters">Sql function parameters</param>
/// <param name="schema">Owning schema</param>
/// <returns>Value of T</returns>
public T SqlScalarResult<T>(DbContext db,
string sql,
SqlParameter[] parameters,
string schema = "dbo") {
if (string.IsNullOrEmpty(sql)) {
throw new ArgumentException("function");
}
if (parameters == null || parameters.Length == 0) {
throw new ArgumentException("parameters");
}
if (string.IsNullOrEmpty(schema)) {
throw new ArgumentException("schema");
}
string cmdText =
$@"SELECT {schema}.{sql}({string.Join(",",
parameters.Select(p => "@" + p.ParameterName).ToList())});";
// ReSharper disable once CoVariantArrayConversion
return db.Database.SqlQuery<T>(cmdText, parameters).FirstOrDefault();
}
}
作为 EF 的扩展方法:
namespace System.Data.Entity {
public static class DatabaseExtensions {
/// <summary>
/// Calls a given Sql function and returns a singular value
/// </summary>
/// <param name="db">Current DbContext instance</param>
/// <typeparam name="T">CLR Type</typeparam>
/// <param name="sql">Sql function</param>
/// <param name="parameters">Sql function parameters</param>
/// <param name="schema">Owning schema</param>
/// <returns>Value of T</returns>
public static T SqlScalarResult<T>(this Database db,
string sql,
SqlParameter[] parameters,
string schema = "dbo") {
if (string.IsNullOrEmpty(sql)) {
throw new ArgumentException("sql");
}
if (parameters == null || parameters.Length == 0) {
throw new ArgumentException("parameters");
}
if (string.IsNullOrEmpty(schema)) {
throw new ArgumentException("schema");
}
string cmdText =
$@"SELECT {schema}.{sql}({string.Join(",",
parameters.Select(p => "@" + p.ParameterName).ToList())});";
// ReSharper disable once CoVariantArrayConversion
return db.SqlQuery<T>(cmdText, parameters).FirstOrDefault();
}
}
}
虽然这里不冒烟,但我建议在认真使用之前进行单元测试。