2015-11-24 11 views
7

У меня есть DataGrid, который имеет коллекцию, связанную с ней через BindingSource:Entity Framework Обновление данных

  bsProducts.DataSource = cc.Products.Local.ToBindingList(); 

Один из объектов в сетке редактируемого (и сохраненный) в другой форме, и я бы например, чтобы обновить сетку в этой форме, теперь я попытался перезагрузить объект, перезагрузить весь локальный контекст, но по какой-то причине он не читает связанные сущности. Теперь, когда я закрываю всю форму и открываю ее снова, все читается.

Чтобы обновить объект, я использую следующий код:

 await cc.Entry<Product>(product).ReloadAsync(); 

Но это не будет загружать любые связанные объекты, которые связаны с Entity продукта. Я снова попытался обновить BindingSource, но не повезло.

+0

После перезагрузки вы снова связываетесь? – MichaelMao

+0

Да, но после ReloadAsync свойство по-прежнему не содержит никаких связанных с ним связанных объектов, а только старых. Я сделал обходной путь, вручную загрузив связанные объекты и назначив их как List <>. – Martin

+0

попытайтесь использовать 'dbProducts.DataBind()' после обновления –

ответ

2

мне довелось работать на «гостя» для объекта объект графа. Увидев ваш вопрос, я дал ему последний штрих, чтобы сделать его полезным в вашем случае (и многих других). Это не настоящий посетитель, как в известном шаблоне посетителя, но он делает в основном одно и то же: он пересекает граф объектов и выполняет какое-то действие для каждой сущности, с которой он сталкивается.

Используя этот метод, вы можете просто позвонить ...

cc.Visit(product, e => cc.Entry(e).Reload()); 

... и вы увидите, что product и все прилипшие объекты перезагружается.

Вот код:

public static class DbContextExtensions 
{ 
    public static void Visit(this DbContext context, object entity, Action<object> action) 
    { 
     Action<object, DbContext, HashSet<object>, Action<object>> visitFunction = null; // Initialize first to enable recursive call. 
     visitFunction = (ent, contxt, hashset, act) => 
      { 
       if (ent != null && !hashset.Contains(ent)) 
       { 
        hashset.Add(ent); 
        act(ent); 
        var entry = contxt.Entry(ent); 
        if (entry != null) 
        { 
         foreach (var np in contxt.GetNavigationProperies(ent.GetType())) 
         { 
          if (np.ToEndMember.RelationshipMultiplicity < RelationshipMultiplicity.Many) 
          { 
           var reference = entry.Reference(np.Name); 
           if (reference.IsLoaded) 
           { 
            visitFunction(reference.CurrentValue, contxt, hashset, action); 
           } 
          } 
          else 
          { 
           var collection = entry.Collection(np.Name); 
           if (collection.IsLoaded) 
           { 
            var sequence = collection.CurrentValue as IEnumerable; 
            if (sequence != null) 
            { 
             foreach (var child in sequence) 
             { 
              visitFunction(child, contxt, hashset, action); 
             } 
            } 
           } 
          } 
         } 
        } 
       } 
      }; 
     visitFunction(entity, context, new HashSet<object>(), action); 
    } 

    // Get navigation properties of an entity type. 
    public static IEnumerable<NavigationProperty> GetNavigationProperies(this DbContext context, Type type) 
    { 
     var oc = ((IObjectContextAdapter)context).ObjectContext; 
     var objectType = ObjectContext.GetObjectType(type); // Works with proxies and original types. 

     var entityType = oc.MetadataWorkspace.GetItems(DataSpace.OSpace).OfType<EntityType>() 
          .FirstOrDefault(et => et.Name == objectType .Name); 
     return entityType != null 
      ? entityType.NavigationProperties 
      : Enumerable.Empty<NavigationProperty>(); 
    } 
} 

Это рекурсивная функция, завернутые в метод расширения. Я завернул рекурсивную часть, чтобы я мог отправить локальный HashSet по графику, который собирает посещенные объекты и тем самым предотвращает циклические ссылки. В основном функция применяет указанное действие к сущности, а затем находит, что ее свойства навигации, которые могут быть ссылками или наборами, получают свои значения (CurrentValue), а затем называет себя для этих значений.

Обратите внимание, что я также проверяю, загружены ли свойства навигации. Без этого может начаться бесконечная цепочка ленивой загрузки.

Также обратите внимание, что это вызывает один запрос для каждого объекта на графике. Это не подходит для графов больших объектов. Если вы хотите обновить большие объемы данных, вы должны использовать другой подход, предпочтительно создать новый контекст.

2

Вы пробовали ApplyCurrentValues ​​() функция, это выглядит как ваш контекст просто isin't принимая новые значения, если вы уже создали функцию обновления, которая делает:

bsProducts.DataSource = cc.Products.Local.ToBindingList(); 
bsProducts.DataBind(); 

Тогда вы migth хотите применить перед этим сделайте это.

Извините, если он не разрешил его, у меня была аналогичная проблема и разрешил это с этим, возможно, не ваше дело.

https://msdn.microsoft.com/en-us/library/dd487246(v=vs.110).aspx

Смежные вопросы