【发布时间】:2011-02-16 15:53:20
【问题描述】:
我正在使用 F# 访问数据库,我最初尝试创建一个函数来创建更新查询是有缺陷的。
let BuildUserUpdateQuery (oldUser:UserType) (newUser:UserType) =
let buf = new System.Text.StringBuilder("UPDATE users SET ");
if (oldUser.FirstName.Equals(newUser.FirstName) = false) then buf.Append("SET first_name='").Append(newUser.FirstName).Append("'" ) |> ignore
if (oldUser.LastName.Equals(newUser.LastName) = false) then buf.Append("SET last_name='").Append(newUser.LastName).Append("'" ) |> ignore
if (oldUser.UserName.Equals(newUser.UserName) = false) then buf.Append("SET username='").Append(newUser.UserName).Append("'" ) |> ignore
buf.Append(" WHERE id=").Append(newUser.Id).ToString()
这不会在第一个之后的任何更新部分之间正确放置,,例如:
UPDATE users SET first_name='Firstname', last_name='lastname' WHERE id=...
当set 子句的第一部分被附加时,我可以放入一个可变变量来跟踪,但这似乎是错误的。
我可以只创建一个元组列表,其中每个元组是 oldtext、newtext、columnname,这样我就可以遍历列表并构建查询,但似乎我应该传入 StringBuilder到递归函数,返回一个boolean,然后将其作为参数传递给递归函数。
这似乎是最好的方法,还是有更好的方法?
更新:
这是我目前使用的解决方案,因为我想让它更通用,所以我只需要为我的实体编写一个抽象类来派生,它们可以使用相同的功能。我选择拆分我如何执行该功能,以便我可以传递如何创建更新的SET 部分,以便我可以用不同的想法进行测试。
let BuildUserUpdateQuery3 (oldUser:UserType) (newUser:UserType) =
let properties = List.zip3 oldUser.ToSqlValuesList newUser.ToSqlValuesList oldUser.ToSqlColumnList
let init = false, new StringBuilder()
let anyChange, (formatted:StringBuilder) =
properties |> Seq.fold (fun (anyChange, sb) (oldVal, newVal, name) ->
match(oldVal=newVal) with
| true -> anyChange, sb
| _ ->
match(anyChange) with
| true -> true, sb.AppendFormat(",{0} = '{1}'", name, newVal)
| _ -> true, sb.AppendFormat("{0} = '{1}'", name, newVal)
) init
formatted.ToString()
let BuildUserUpdateQuery (oldUser:UserType) (newUser:UserType) (updatequery:UserType->UserType->String) =
let buf = StringBuilder("UPDATE users SET ");
buf.AppendFormat(" {0} WHERE id={1}", (updatequery oldUser newUser), newUser.Id)
let UpdateUser conn (oldUser:UserType) (newUser:UserType) =
let query = BuildUserUpdateQuery oldUser newUser BuildUserUpdateQuery3
execNonQuery conn (query.ToString())
【问题讨论】:
标签: sql f# functional-programming