[英]Lambda expression to SQL UPDATE statement using C#
Is library or code available to create SQL Update statements from lambda expressions? 库或代码是否可用于从lambda表达式创建SQL Update语句? We would like to use strongly-typed lambda expressions to do updates instead of calling the object before hand, or using strings.
我们希望使用强类型的lambda表达式来进行更新,而不是事先调用对象或使用字符串。 I'm thinking of something like this.
我在考虑这样的事情。
Update<Task>(
u => u.UserID = 1, u.TaskCount += 1, //Update
w => w.Priority != "High" && (w.Status != "Complete" || w.Status == null) //Where
);
Which would roughly translate to.. 哪个会粗略地翻译成..
UPDATE Tasks SET UserID = 1, TaskCount = TaskCount + 1
WHERE Priority <> "High" AND (Status <> "Complete" OR Status = null)
I should mention we are currently using the Entity Framework and Postgres. 我应该提到我们目前正在使用Entity Framework和Postgres。
I finally figured out a way to do this. 我终于想出办法来做到这一点。 Basically, get the generated SQL from the Entity Framework, LINQ-to-SQL, or another ORM, then parse the WHERE clause.
基本上,从实体框架,LINQ-to-SQL或其他ORM获取生成的SQL,然后解析WHERE子句。 That way I don't have to parse the lambda manually.
这样我就不必手动解析lambda了。 Then create an UPDATE clause from an anonymous type.
然后从匿名类型创建UPDATE子句。 The result looks like:
结果如下:
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");
This allows me to update/delete values WITHOUT pulling them first. 这允许我更新/删除值而不先拉它们。
And the code for it looks like this... 它的代码看起来像这样......
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\"");
}
And for those who like Extensions: 对于那些喜欢扩展的人:
public static async Task Update<T>(this DbSet<T> objectContext, Action<T> updateStatement, Expression<Func<T, bool>> where) where T : class
{
var items = objectContext.AsQueryable();
// filter with the Expression if exist
if (where != null)
items = items.Where(where);
// perform the Action on each item
await items.ForEachAsync(updateStatement);
}
Usage: 用法:
await context.Organisations.Update(s => s.LastDateBasicEvent = LastDayOfSchool, null);
context.SaveChanges();
Tested on EF6 在EF6上测试过
You can do something like this, but there will be limitations on what can be translated into SQL and what needs to be pulled back to your application. 你可以做这样的事情 ,但不会有什么可以转化为SQL,需要拉回你的应用有什么限制。
What you need to do is give your Update
method both an Action
(this is the 'update' part) and an Expression
(as the 'where' clause). 你需要做的是给你的
Update
方法一个Action
(这是'update'部分)和一个Expression
(作为'where'子句)。
public void Update(Action<T> updateStatement, Expression<Func<T, bool>> where)
{
// get your object context & objectset, cast to IQueryable<T>
var table = (IQueryable<T>)objectContext.CreateObjectSet<T>();
// filter with the Expression
var items = table.Where(where);
// perform the Action on each item
foreach (var item in items)
{
updateStatement(item);
}
// save changes.
}
Then you can call your Update with something like 然后你可以用类似的东西来调用你的更新
repository.Update(s => s.Name = "Me", w => w.Id == 4);
I found this article about building and executing an "SQL update on-top of the Entity Framework". 我发现这篇文章是关于构建和执行“实体框架顶部的SQL更新”。 Maybe it's useful for you.
也许它对你有用。
http://blogs.msdn.com/b/alexj/archive/2007/12/07/rolling-your-own-sql-update-on-top-of-the-entity-framework-part-1.aspx http://blogs.msdn.com/b/alexj/archive/2007/12/07/rolling-your-own-sql-update-on-top-of-the-entity-framework-part-1.aspx
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.