如何使EF使用字符串concat构建更新SQL
本文关键字:concat 构建 更新 SQL 字符串 何使 EF | 更新日期: 2023-09-27 18:14:25
. NET MVC 4/EF 5 web应用程序的数据库,我有一个表的评论列,我想连接新的评论。在传统的T-SQL中,我会这样写:
UPDATE MyTable SET Comments = 'Hi' + CHAR(13)+CHAR(10) + Comments WHERE ID = 2
我发现使用EF的方法linq (uow +存储库模式——我很遗憾),我必须首先查询Comments的当前值,并将我的新注释添加到它:
StringBuilder displayComment = new StringBuilder();
var item = uow.MyRepos.Where(i => i.ID == 2);
item.Comments = displayComment.Append("Hi")
.Append(Environment.NewLine)
.Append(item.Comments)
.ToString();
uow.Save();
是否有任何方法可以在不需要查询DB的情况下编写此更新?我想让EF以某种方式生成上面的t-sql。评论可能很长,我不在乎它包含什么。性能是一个问题。
标准更新设置字段,我假设您需要保留该功能,否则您将无法编辑以前的注释。这意味着你有一个特殊的更新情况。我会在MyTable
的存储库中添加一个方法来运行您想要的sql:
public int PrependComment(int id, String comment)
{
String sql = "UPDATE MyTable SET Comments = {0} +
CHAR(13)+CHAR(10) + Comments WHERE ID = {1}";
return dbContext.Database.ExecuteSqlCommand(sql, comment, id);
}
我认为你唯一可以玩的是使用DbCommandInterceptor
。您可以拦截每个非查询执行的命令(更新、删除、插入),并在实际执行命令之前修改命令文本。这里的代码只是为了理解如何做到这一点。您可以重构它以方便使用:
public class PrependTextInterceptor : DbCommandInterceptor
{
const string table = "MyTable";
const string column = "Comments";
public override void NonQueryExecuting(DbCommand command, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext<int> interceptionContext)
{
command.CommandText = Regex.Replace(command.CommandText,
string.Format(@"(?i:(?<=^UPDATE '[.+']'.'[{0}']'r'nSET .* '[{1}'] = ).+?(?=(,|'r'n)))", table, column), "$& + " + column);
base.NonQueryExecuting(command, interceptionContext);
}
}
//Usage
DbInterception.Add(new PrependTextInterceptor());
//after this every time you set the Comments property
//it will be understood as prepending
item.Comments = displayComment.Append("Hi")
.Append(Environment.NewLine).ToString();
只是一个注意,如果你加载你的item
正常,它的Comments
属性也应该加载。因此,您失去了在前置之前不首先加载它的好处。我认为你需要使用Attach
,你只需要知道ID
能够更新它而不加载它(就像通过查询context.Set<MyTable>().Single(e => e.ID == 2)
, Comments
那么应该是肯定加载)。