2013-08-11 86 views
18

Tôi muốn làm mới tất cả các đơn vị của DbContext của tôi mà không tái tạo nó, tôi đã thử sau đây và không ai trong số họ có ý nghĩa:Làm thế nào để Refresh DbContext

var context = ((IObjectContextAdapter)myDbContext).ObjectContext; 

var refreshableObjects = (from entry in context.ObjectStateManager.GetObjectStateEntries(
            EntityState.Added 
            | EntityState.Deleted 
            | EntityState.Modified 
            | EntityState.Unchanged) 
          where entry.EntityKey != null 
          select entry.Entity); 

context.Refresh(RefreshMode.StoreWins, refreshableObjects); 
//....................................................................... 
foreach (var entry in this.Orm.ChangeTracker.Entries()) 
{ 
    entry.State = EntityState.Unchanged; 
} 
this.Orm.ChangeTracker.DetectChanges(); 

Và người duy nhất mà làm mới của tôi DbContext:

foreach (var i in this.Orm.ChangeTracker.Entries()) 
    i.Reload(); 

Nhưng quá chậm. Bạn có thể giúp tôi chọn đúng cách không?

+1

Bạn đã thử context.Refresh (RefreshMode, Entity) và xem trong trình gỡ lỗi và sql màn hình nếu nó thực sự được cập nhật? – yonexbat

+0

@yonexbat: Tôi đã tự thay đổi dữ liệu trong sql và được gọi là 'context.Refresh (RefreshMode, Entity)' nhưng không thay đổi được cập nhật và thực hiện cùng kịch bản với 'i.Reload();' và tất cả các thay đổi được cập nhật trong 'DbContext'. – Mohsen

Trả lời

29

Tôi chỉ thấy rằng kết quả Enumerable sẽ được đánh giá vì phương pháp Refresh coi đó là đối tượng và không đánh giá nó.

var context = ((IObjectContextAdapter)myDbContext).ObjectContext; 
var refreshableObjects = (from entry in context.ObjectStateManager.GetObjectStateEntries(
              EntityState.Added 
              | EntityState.Deleted 
              | EntityState.Modified 
              | EntityState.Unchanged) 
          where entry.EntityKey != null 
          select entry.Entity).ToList(); 

context.Refresh(RefreshMode.StoreWins, refreshableObjects); 

Và tôi thích như sau:

var refreshableObjects = myDbContext.ChangeTracker.Entries().Select(c=>c.Entity).ToList(); 
context.Refresh(RefreshMode.StoreWins, refreshableObjects); 
+2

Sử dụng phương pháp của bạn, tôi nhận được: Phần tử ở chỉ mục 0 trong tập hợp các đối tượng cần làm mới ở trạng thái được thêm vào. Không thể làm mới các đối tượng trong trạng thái này. –

+2

@isti_spl: bạn nên khôi phục tốt hơn trước khi tham khảo 'if (entry.State == EntityState.Added) entry.State = EntityState.Detached; // ...' – Mohsen

+0

mục nhập.State là chỉ đọc – HICURIN

9

Tôi đã kiểm tra này và id hoạt động tốt:

//Search 
Box box = dbContext.Boxes.FirstOrDefault(x => x.BoxId == 45); 

//breakpoint here, change Name of Box by sql management studio 

//Refresh 
var context = ((IObjectContextAdapter)dbContext).ObjectContext; 
context.Refresh(System.Data.Entity.Core.Objects.RefreshMode.StoreWins, box); 

//Check refresh and if it is in context 
box = dbContext.Boxes.FirstOrDefault(x => x.BoxId == 45); 

Bạn có chắc chắn nó là như nhau db-bối cảnh?

+0

Xin lỗi để thêm nó làm câu trả lời, nhưng tôi không biết cách định dạng văn bản trong nhận xét. – yonexbat

+0

: Cảm ơn, tôi sử dụng nó để làm mới một thực thể, nhưng tôi cần phải làm mới tất cả các thực thể của 'DbContext' không chỉ là một' Entity' hoặc 'Entity Collection' hoặc' Entities 'của một số Entity'. – Mohsen

+1

Ok. Tôi sẽ tạo lại DbContext. myDbContext = new MyDbContext(); – yonexbat

3
using System.Data.Entity.Core.Objects; 
using System.Data.Entity.Infrastructure; 
using System.Linq; 

namespace System.Data.Entity 
{ 
    public static class DbContextExtensions 
    { 
     /// <summary> 
     /// Refresh non-detached entities 
     /// </summary> 
     /// <param name="dbContext">context of the entities</param> 
     /// <param name="refreshMode">store or client wins</param> 
     /// <param name="entityType">when specified only entities of that type are refreshed. when null all non-detached entities are modified</param> 
     /// <returns></returns> 
     public static DbContext RefreshEntites(this DbContext dbContext, RefreshMode refreshMode, Type entityType) 
     { 
      //https://christianarg.wordpress.com/2013/06/13/entityframework-refreshall-loaded-entities-from-database/ 
      var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext; 
      var refreshableObjects = objectContext.ObjectStateManager 
       .GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged) 
       .Where(x => entityType == null || x.Entity.GetType() == entityType) 
       .Where(entry => entry.EntityKey != null) 
       .Select(e => e.Entity) 
       .ToArray(); 

      objectContext.Refresh(RefreshMode.StoreWins, refreshableObjects); 

      return dbContext; 
     } 

     public static DbContext RefreshAllEntites(this DbContext dbContext, RefreshMode refreshMode) 
     { 
      return RefreshEntites(dbContext: dbContext, refreshMode: refreshMode, entityType: null); //null entityType is a wild card 
     } 

     public static DbContext RefreshEntites<TEntity>(this DbContext dbContext, RefreshMode refreshMode) 
     { 
      return RefreshEntites(dbContext: dbContext, refreshMode: refreshMode, entityType: typeof(TEntity)); 
     } 
    } 
} 
2

Trong một số trường hợp, nếu một bộ sưu tập đã được cập nhật bởi một ứng dụng của bên thứ ba, bộ sưu tập có thể không được nạp lại khi làm mới đối tượng của bộ sưu tập.

tôi đã có trường hợp tôi đã có một đối tượng A với một đến nhiều relashionship đến một đối tượng B.

Application 1 tải một đối tượng A với A.ListB trống. Ứng dụng 2 điền vào bộ sưu tập A.ListB. Ứng dụng 1 tải lại đối tượng A.

Với giải pháp trên, A.ListB vẫn trống. Tôi phải tải lại bộ sưu tập A.ListB một cách rõ ràng.

Đây là một cách chung chung để có tất cả bộ sưu tập reloaded:

var context = ((IObjectContextAdapter)this).ObjectContext; 

// detach all added entities 
ChangeTracker.Entries().Where(e => e.State == EntityState.Added).ToList().ForEach(e => e.State = EntityState.Detached); 

// select entities 
var refreshableObjects = ChangeTracker.Entries().Select(e => e.Entity).ToList(); 

// refresh each refreshable object 
foreach (var @object in refreshableObjects) 
{ 
    // refresh each collection of the object 
    context.ObjectStateManager.GetRelationshipManager(@object).GetAllRelatedEnds().Where(r => r.IsLoaded).ToList().ForEach(c => c.Load()); 

    // refresh the object 
    context.Refresh(RefreshMode.StoreWins, @object); 
}