在我的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。评论可能很冗长,我不关心它包含的内容。表现是一个问题。
提前致谢。
答案 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);
}