2015-09-25 16 views
5

Trong cơ sở dữ liệu ASP.NET MVC 4/EF 5 của ứng dụng web của tôi, tôi có một bảng với cột Nhận xét mà tôi muốn kết hợp các nhận xét mới. Trong truyền thống T-SQL, tôi muốn viết: Làm cách nào để EF xây dựng bản cập nhật SQL bằng chuỗi concat?

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

Tôi tìm thấy với phương pháp LINQ cho EF (UOW + mô hình kho - mà tôi hối tiếc), tôi phải đầu tiên truy vấn giá trị hiện tại của nhận xét và thêm vào trước nhận xét mới của tôi về nó:

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

Có cách nào để viết bản cập nhật này mà không cần truy vấn DB không? Tôi muốn bằng cách nào đó có được EF để tạo ra t-sql ở trên. Các bình luận có thể dài và tôi không quan tâm về những gì nó có chứa. Hiệu suất là một mối quan tâm.

Xin cảm ơn trước.

+1

tôi thêm này ở đây như là một lời nhận xét, bởi vì nó không phải là một câu trả lời: bạn nói đúng về những gì EF có thể làm, và làm thế nào để làm đi. Tuy nhiên, nếu bạn cần làm điều gì đó mà EF không hỗ trợ, bạn không cần phải tốn nhiều thời gian để cố gắng hoàn thành nó. Bạn chỉ có thể thực hiện một truy vấn tùy chỉnh hoặc thủ tục được lưu trữ để giải quyết vấn đề của bạn. Nó có thể trông ít thông minh hơn, nhưng tôi không nghĩ là vậy. Có rất nhiều điều mà EF không thể làm, nhưng * bạn được phép * làm những việc theo cách khác, thay vì cố gắng thực hiện các giải pháp ma thuật hoặc hack cho vấn đề của bạn. Cùng một vấn đề phát sinh với cập nhật hàng loạt hoặc xóa. Giải pháp là đơn giản – JotaBe

+0

Cảm ơn bạn đã nói điều này @ JotaBe - Tôi đã cố gắng để ở lại trong dòng, nhưng đôi khi đó không phải là giải pháp tốt nhất. – LoJo

+0

@LoJo bạn nói *** Tôi muốn bằng cách nào đó khiến EF tạo ra t-sql ở trên *** - vì vậy đó là lý do tại sao câu hỏi của bạn đã được upvoted để *** 5 *** (tại thời điểm tôi đã viết này). Nếu không nó chỉ là một yêu cầu bình thường, không có gì đặc biệt và thậm chí không phải là một câu trả lời cần phải được thêm vào. Bạn nên hiểu về điều đó với một số nhận xét và xóa câu hỏi ngay lập tức. – Hopeless

Trả lời

0

Cập nhật tiêu chuẩn đặt trường và tôi cho rằng bạn cần phải giữ chức năng đó, nếu không bạn sẽ không thể chỉnh sửa các nhận xét trước đó. Vì vậy, điều đó có nghĩa là bạn có một trường hợp cập nhật đặc biệt. Tôi sẽ thêm một phương pháp để kho cho MyTable chạy sql bạn muốn:

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

Cảm ơn vì điều này.Tôi bị mất thị lực khi làm mọi thứ theo cách trực tiếp. – LoJo

0

Tôi nghĩ rằng điều duy nhất bạn có thể chơi cùng là sử dụng DbCommandInterceptor. Bạn có thể chặn tất cả các lệnh không được truy vấn (cập nhật, xóa, chèn) và sửa đổi văn bản lệnh trước khi nó thực sự được thực hiện. Mã ở đây chỉ là để hiểu làm thế nào nó có thể được thực hiện. Bạn có thể cấu trúc lại nó để sử dụng thuận tiện hơn:

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

Chỉ cần một lưu ý hơn, Nếu bạn tải bạn item bình thường, sở hữu Comments của nó cũng nên được nạp. Vì vậy, bạn mất lợi ích khi không tải nó trước trước khi đăng ký trước. Tôi nghĩ rằng bạn cần phải sử dụng Attach trong đó bạn chỉ cần phải biết ID để có thể cập nhật nó mà không cần nạp nó (như là thông qua một truy vấn context.Set<MyTable>().Single(e => e.ID == 2), Comments rồi nên chắc chắn nạp).

+0

Cảm ơn bạn đã đăng bài này. Tôi đã quyết định đi với sự kết hợp của đề nghị của @JotaBe và Colin, nhưng tôi nghĩ rằng những người khác có thể thấy nó rất hữu ích. – LoJo

Các vấn đề liên quan