如何使EF使用字符串concat构建更新SQL?

时间:2015-09-25 02:38:29

标签: c# sql-server entity-framework linq tsql

在我的ASP.NET MVC 4 / EF 5 Web应用程序的数据库中,我有一个带有Comments列的表,我想将新注释连接到。在传统的T-SQL中,我写道:

UPDATE MyTable SET Comments = 'Hi' + CHAR(13)+CHAR(10) + Comments WHERE ID = 2

我找到了方法linq for EF(uow + repository pattern - 我很遗憾),我必须首先查询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();

有没有办法编写此更新而无需查询数据库?我想以某种方式让EF生成上面的t-sql。评论可能很冗长,我不关心它包含的内容。表现是一个问题。

提前致谢。

2 个答案:

答案 0 :(得分:0)

我认为您唯一可以使用的是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然后应该 肯定已加载 )。

答案 1 :(得分:0)

标准更新设置了该字段,我假设您需要保留该功能,否则您将无法编辑以前的注释。这意味着您有一个特殊的更新案例。我会在运行你想要的sql的MyTable的存储库中添加一个方法:

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);
}