c# - 使用 C# 将 Lambda 表达式转换为 SQL UPDATE 语句

标签 c# entity-framework lambda

是否有可用于从 lambda 表达式创建 SQL 更新语句的库或代码?我们希望使用强类型的 lambda 表达式来进行更新,而不是事先调用对象或使用字符串。我在想这样的事情。

Update<Task>(
    u => u.UserID = 1, u.TaskCount += 1, //Update
    w => w.Priority != "High" && (w.Status != "Complete" || w.Status == null) //Where
);

这将大致转化为..

UPDATE Tasks SET UserID = 1, TaskCount = TaskCount + 1
WHERE Priority <> "High" AND (Status <> "Complete" OR Status = null)

我应该提到我们目前正在使用 Entity Framework 和 Postgres。

最佳答案

我终于想出了一个办法来做到这一点。基本上,从 Entity Framework 、LINQ-to-SQL 或其他 ORM 获取生成的 SQL,然后解析 WHERE 子句。这样我就不必手动解析 lambda。然后从匿名类型创建一个 UPDATE 子句。结果如下:

Update<Task>(
    new { UserID = 1, TaskCount = IncrementOf(1), SomeOtherField = DdNull } //Update
    w => w.Priority != "High" && (w.Status != "Complete" || w.Status == null) //Where
);

Delete<Task>(w => w.UserID == userID && w.Status != "Complete");

这允许我更新/删除值而无需先拉取它们。

它的代码看起来像这样......

protected void Update<T>(object values, Expression<Func<T, bool>> where) where T : class
{
    Domain.ExecuteStoreCommand(
        "UPDATE {0} SET {1} WHERE {2};",
        GetTableString<T>(),
        GetUpdateClauseString(values),
        GetWhereClauseString(where)
        );
}

protected string GetUpdateClauseString(object obj)
{
    string update = "";
    var items = obj.ToDictionary();
    foreach (var item in items)
    {
        //Null
        if (item.Value is DBNull) update += string.Format("{0} = NULL", GetFieldString(item.Key));

        //Increment
        else if (item.Value is IncrementExpression) update += string.Format("{0} = {0} + {1}", GetFieldString(item.Key), ((IncrementExpression)item.Value).Value.ToString());

        //Decrement
        else if (item.Value is DecrementExpression) update += string.Format("{0} = {0} - {1}", GetFieldString(item.Key), ((DecrementExpression)item.Value).Value.ToString());

        //Set value
        else update += string.Format("{0} = {1}", GetFieldString(item.Key), GetValueString(item.Value));

        if (item.Key != items.Last().Key) update += ", ";
    }
    return update;
}

protected string GetWhereClauseString<T>(Expression<Func<T, bool>> where) where T : class
{
    //Get query
    var query = ((IQueryable<T>)Domain.CreateObjectSet<T>());
    query = query.Where(where);
    ObjectQuery queryObj = (ObjectQuery)query;

    //Parse where clause
    string queryStr = queryObj.ToTraceString();
    string whereStr = queryStr.Remove(0, queryStr.IndexOf("WHERE") + 5);

    //Replace params
    foreach (ObjectParameter param in queryObj.Parameters)
    {
        whereStr = whereStr.Replace(":" + param.Name, GetValueString(param.Value));
    }

    //Replace schema name
    return whereStr.Replace("\"Extent1\"", "\"Primary\"");
}

关于c# - 使用 C# 将 Lambda 表达式转换为 SQL UPDATE 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5073464/

相关文章:

c# - 压缩 c# dnn 模块设置代码

c# - 如何在 IIS 中授予对 Web API 应用程序的写入权限?

c# - EF6 在单次调用中获取计数

c# - EntityFramework Code First继承与自定义鉴别器

java - Netbeans 中的 Lambda 表达式问题

c# - 在MVVM中处理MouseEnter over命令

entity-framework - EF/Postgresql 数据库优先方法可能吗?

c# - 使用 LINQ/lambdas 构建以逗号分隔的内部异常消息字符串

c++ - 如果在 lambda 中,MSVC 不尊重 constexpr

javascript - 离开页面时从 Razor View 中的 session 中删除项目