2010-11-18 23 views
79

Cho phép nói rằng tôi truy vấn cơ sở dữ liệu và tải danh sách các mục. Sau đó, tôi mở một trong các mục ở dạng xem chi tiết và thay vì truy vấn lại mục đó ra khỏi cơ sở dữ liệu, tôi tạo một thể hiện của mục từ nguồn dữ liệu trong danh sách.Cập nhật bản ghi mà không cần truy vấn đầu tiên?

Có cách nào tôi có thể cập nhật bản ghi cơ sở dữ liệu mà không tìm nạp bản ghi của mục riêng lẻ không?

Đây là một mẫu như thế nào tôi đang làm bây giờ:

dataItem itemToUpdate = (from t in dataEntity.items 
           where t.id == id 
           select t).FirstOrDefault(); 

Sau đó, sau khi kéo kỷ lục tôi cập nhật một số giá trị trong mục đó và đẩy kỷ lục trở lại:

itemToUpdate.itemstatus = newStatus; 
dataEntity.SaveChanges(); 

Tôi sẽ nghĩ sẽ có cách nào tốt hơn để làm điều này, bất kỳ ý tưởng nào?

+2

Nó không phải là một cách khủng khiếp xấu o làm việc. Bạn có quyền truy cập đồng thời vào bảng đó không? –

+0

Tôi nghĩ đây là cách sử dụng mà một ORM như EF chính xác ở đó để phục vụ. Để cho phép các hoạt động trong ngữ cảnh của ứng dụng được thực hiện trên các đối tượng mà bạn muốn tạo/sửa đổi/xóa, mà không cần quan tâm đến việc triển khai DB cơ bản? –

+27

Tôi nghĩ cho các nhà phát triển có một nền tảng trong TSQL cố gắng chấp nhận và nắm lấy ORM, một chút không hiệu quả để tra cứu một bản ghi chỉ để cập nhật nó và không bao giờ sử dụng dữ liệu được tìm nạp. Khái niệm này mà một nhà phát triển không cần phải quan tâm đến việc triển khai DB cơ bản là một crock. Nhà phát triển càng biết nhiều về toàn bộ hệ thống thì giải pháp càng tốt. Tùy chọn không bao giờ là một điều xấu. – barrypicker

Trả lời

61

Bạn nên sử dụng phương thức Attach().

Attaching and Detaching Objects

+13

bạn có thể cung cấp một ví dụ không? –

+14

context.Products.Attach (sản phẩm); context.Entry (product) .State = EntityState.Modified; – Gabriel

+4

@Gabriel Sẽ không cập nhật tất cả các thuộc tính này? Điều gì xảy ra nếu tôi chỉ muốn sửa đổi một đơn? –

0

Nói chung, nếu bạn sử dụng Entity Framework để truy vấn tất cả các mục, và bạn đã lưu các đối tượng tổ chức nào, bạn có thể cập nhật các mặt hàng cá nhân trong đối tượng thực thể và gọi SaveChanges() khi bạn đã kết thúc. Ví dụ:

var items = dataEntity.Include("items").items; 
// For each one you want to change: 
items.First(item => item.id == theIdYouWant).itemstatus = newStatus; 
// After all changes: 
dataEntity.SaveChanges(); 

Việc truy xuất một mục bạn muốn không tạo truy vấn mới.

+0

Câu trả lời thú vị, có ai khác đã xác nhận điều này không? – Ian

+3

Điều này cũng giống như vấn đề của OP: tìm nạp toàn bộ bản ghi, sau đó cập nhật nó. .First() deserializes đối tượng. – Jerther

27

Bạn cũng có thể sử dụng SQL trực tiếp đối với cơ sở dữ liệu bằng cách sử dụng ngữ cảnh của kho dữ liệu. Ví dụ:

dataEntity.ExecuteStoreCommand 
    ("UPDATE items SET itemstatus = 'some status' WHERE id = 123 "); 

Vì lý do hiệu suất, bạn có thể chuyển các biến thay vì một chuỗi SQL được mã hóa cứng. Điều này sẽ cho phép SQL Server lưu trữ truy vấn và sử dụng lại với các tham số. Ví dụ:

dataEntity.ExecuteStoreCommand 
    ("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 }); 

CẬP NHẬT - cho EF 6,0

dataEntity.Database.ExecuteSqlCommand 
     ("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 }); 
+6

tại sao bạn hạ cấp câu trả lời này mà không để lại nhận xét. Đề xuất này đề cập đến câu hỏi của tác giả gốc tại chỗ. – barrypicker

+11

'ExecuteStoreCommand' không thực sự là một cách EF để làm điều này, nó chỉ sử dụng' DbConnection' chứa bên trong 'DbContext' để thực hiện một lệnh. Nó không phải là cơ sở dữ liệu bất khả tri, hãy để một mình duy trì thuyết bất khả tri (ví dụ, ví dụ này sẽ sụp đổ nếu OP chuyển sang XML). –

+7

@ just.another.programmer - với sức mạnh to lớn có trách nhiệm lớn. – barrypicker

2

Bài viết này như một phần của Microsoft's Getting Started giải thích trạng thái thực thể và làm thế nào để làm điều này:

Add/Attach and Entity States

Nhìn vào phần 'Đính kèm thực thể hiện tại nhưng đã sửa đổi vào ngữ cảnh'

Bây giờ tôi tắt để đọc phần còn lại của các hướng dẫn này.

6

Nếu DataItem có các trường EF sẽ pre-xác nhận (như lĩnh vực phi nullable), chúng tôi sẽ phải vô hiệu hóa mà xác nhận cho trường hợp này:

DataItem itemToUpdate = new DataItem { Id = id, Itemstatus = newStatus }; 
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true; 
dataEntity.Configuration.ValidateOnSaveEnabled = false; 
dataEntity.SaveChanges(); 
//dataEntity.Configuration.ValidateOnSaveEnabled = true; 

Nếu không chúng ta có thể cố gắng đáp ứng các pre-validation và vẫn chỉ cập nhật các cột duy nhất:

DataItem itemToUpdate = new DataItem 
{ 
    Id = id, 
    Itemstatus = newStatus, 
    NonNullableColumn = "this value is disregarded - the db original will remain" 
}; 
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true; 
dataEntity.SaveChanges(); 

Giả sử dataEntity là một System.Data.Entity.DbContext

Bạn có thể xác minh thứ e truy vấn được tạo ra bằng cách thêm này đến DbContext:

/*dataEntity.*/Database.Log = m => System.Diagnostics.Debug.Write(m); 
3

Mã:

ExampleEntity exampleEntity = dbcontext.ExampleEntities.Attach(new ExampleEntity { Id = 1 }); 
exampleEntity.ExampleProperty = "abc"; 
dbcontext.Entry<ExampleEntity>(exampleEntity).Property(ee => ee.ExampleProperty).IsModified = true; 
dbcontext.Configuration.ValidateOnSaveEnabled = false; 
dbcontext.SaveChanges(); 

Kết quả TSQL:

exec sp_executesql N'UPDATE [dbo].[ExampleEntities] 
SET [ExampleProperty ] = @0 
WHERE ([Id] = @1) 
',N'@0 nvarchar(32),@1 bigint',@0='abc',@1=1 

Lưu ý:

Các "IsModified = true" là cần thiết vì khi bạn tạo đối tượng ExampleEntity mới (chỉ với thuộc tính Id được điền) tất cả các thuộc tính khác có giá trị mặc định của chúng (0, null, v.v.). Nếu bạn muốn cập nhật DB với "giá trị mặc định", thay đổi sẽ không được phát hiện bởi khung thực thể và sau đó DB sẽ không được cập nhật.

Trong ví dụ:

exampleEntity.ExampleProperty = null; 

sẽ không làm việc mà không có dòng "IsModified = true", bởi vì ExampleProperty bất động sản, đã null khi bạn tạo ra các đối tượng ExampleEntity rỗng, bạn cần phải nói với EF rằng đây cột phải được cập nhật và đây là mục đích của dòng này.

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