mic*_*arz 5 entity-framework asp.net-core
处理我需要包含在 WHERE IN 查询中的项目列表的正确方法是什么?在我的用例中,我需要使用日期时间列表。我当前的解决方案非常糟糕,因为我在查询中嵌入了数据,并且我更喜欢使用查询参数。
var n = String.Join(",", dates.Select(item => $"'{item.ToString()}'::timestamp"));
var q = $@"
SELECT c.date AS date, a.id AS user_id, a.user_name AS user_name, a.email AS user_email, COALESCE(sum(te.amount), 0) AS summary
FROM asp_net_users a
CROSS JOIN (SELECT *
FROM calendar
WHERE date IN({n})
) c
LEFT JOIN time_entries te on a.id = te.user_id AND c.date = te.date
WHERE a.department_guid = '95b7538d-3830-48d7-ba06-ad7c51a57191'
GROUP BY c.date, a.id
HAVING COALESCE(sum(te.amount), 0) > 480
ORDER BY c.date
";
Run Code Online (Sandbox Code Playgroud)
当我尝试在查询参数中使用日期作为数组时,我收到以下错误:
operator does not exist: timestamp without time zone = timestamp[]
Run Code Online (Sandbox Code Playgroud)
如果很少使用数组输入,这可能是过度设计,但我认为值得尝试。您可以尝试自定义数据库参数和扩展来解决您的问题
首先要事。您需要自定义 DbParameter 类型
public class SqlListParameter : DbParameter
{
private string _internalName;
protected string InternalName
{
get => _internalName;
set => _internalName = NormalizeParameterName(value);
}
public override DbType DbType { get; set; }
public override ParameterDirection Direction { get; set; }
public override bool IsNullable { get; set; }
public override string SourceColumn { get; set; }
public override object Value { get; set; }
public override bool SourceColumnNullMapping { get; set; }
public override int Size { get; set; }
public override string ParameterName
{
get => InternalName;
set => InternalName = value;
}
public override void ResetDbType()
{
}
public SqlListParameter(string parameterName)
{
InternalName = parameterName;
}
internal static string NormalizeParameterName(string parameterName)
{
return string.IsNullOrWhiteSpace(parameterName) || parameterName.First() == '@'
? parameterName
: "@" + parameterName;
}
}
Run Code Online (Sandbox Code Playgroud)
并扩展Database.SqlQuery以能够使用我们的自定义 DbParameter
public static class SqlQueryExtensions
{
public static DbRawSqlQuery<TElement> ExtendedSqlQuery<TElement>(this Database db, string sql, params object[] parameters)
{
var listParameters = parameters.Where(n => n.GetType() == typeof(SqlListParameter)).ToArray();
sql = listParameters.Aggregate(sql, (dbSql, parameter) => ApplyList(dbSql, parameter as SqlListParameter));
parameters = parameters.Where(n => n.GetType() != typeof(SqlListParameter)).ToArray();
return db.SqlQuery<TElement>(sql, parameters);
}
private static string ApplyList(string sql, SqlListParameter parameter)
{
var list = parameter.Value as IEnumerable<int>;
if (list == null)
throw new SqlListException("SqlListParameter value should has could be casted to IEnumerable<int>");
var joinedListItems = string.Join(",", list);
return sql.Replace(parameter.ParameterName, joinedListItems);
}
}
Run Code Online (Sandbox Code Playgroud)
最后你可以像下面这样使用它
using (var context = new TestDbContext())
{
var parameters = new object[]
{
new SqlListParameter("@identsList") { Value = new [] { 1, 2 }},
new SqlParameter("@nameParam", SqlDbType.VarChar) { Value = "Test1"},
};
var isFoundEntry = context.Database.ExtendedSqlQuery<TestEntity>("select * from TestEntities where Id in (@identsList) and name=@nameParam", parameters).Any();
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你。
| 归档时间: |
|
| 查看次数: |
1224 次 |
| 最近记录: |