EntityKey и ApplyPropertyChanges ()

Так как blockize и getAvailableBlocks

устарели

, этот код можно использовать

примечание на основе приведенного выше ответа пользователя 802467

public long sd_card_free(){
    File path = Environment.getExternalStorageDirectory();
    StatFs stat = new StatFs(path.getPath());
    long availBlocks = stat.getAvailableBlocksLong();
    long blockSize = stat.getBlockSizeLong();
    long free_memory = availBlocks * blockSize;

    return free_memory;
}

мы можем использовать getAvailableBlocksLong и getBlockSizeLong

6
задан Zack Peterson 22 May 2009 в 19:01
поделиться

3 ответа

Причина сбоя второго блока кода заключается в том, что EF не может найти объект в ObjectStateManager - т.е. когда он извлекает объекты из базы данных, он помещает их в диспетчер состояний, чтобы отслеживать их - это похоже на Образец карты идентичности . Несмотря на наличие EntityKey, ваш объект не находится в диспетчере состояний, поэтому EF не может сохранить изменения. Вы можете обойти это, поместив объект в диспетчер состояний самостоятельно, но вы должны быть немного скрытными.

Это работает:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
  var entitySetName = db.DefaultContainerName + "." + model.GetType().Name;
  var entityKey = new System.Data.EntityKey(entitySetName, "Id", model.Id);

  db.Attach(new Department{Id = id, EntityKey = entityKey});
  db.AcceptAllChanges();

  db.ApplyPropertyChanges(entitySetName, model);
  db.SaveChanges();
}

... но это не очень чисто. По сути, это присоединение «пустого» объекта только с ключом сущности, принятие всех изменений и последующий вызов ApplyPropertyChanges с реальными обновленными значениями.

Здесь ' s то же самое, заключенное в метод расширения - это должно работать для всего, что использует единственный столбец db для первичного ключа. Единственная интересная часть вызова метода заключается в том, что вам нужно указать ему, как найти ключевое свойство через делегат в качестве второго аргумента метода расширения:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
  db.ApplyDetachedPropertyChanges(model, x => x.Id);
  db.SaveChanges();
}

и метода расширения:

public static class EfExtensions
{
  public static void ApplyDetachedPropertyChanges<T>(this ObjectContext db, T entity, Func<T, int> getIdDelegate)
  where T : EntityObject
  {
    var entitySetName = db.DefaultContainerName + "." + entity.GetType().Name;
    var id = getIdDelegate(entity);
    var entityKey = new EntityKey(entitySetName, "Id", id);

    db.Attach(new Department {Id = id, EntityKey = entityKey});
    db.AcceptAllChanges();

    db.ApplyPropertyChanges(entitySetName, entity);
  }
}

Когда метод расширения вызывает AcceptAllChanges, вам нужно быть осторожным при вызове этого, если вы выполняете обновления сразу для нескольких объектов - вы можете легко «потерять» обновления, если не будете осторожны. Следовательно, этот подход действительно подходит только для простых сценариев обновления - например, для множества методов действий MVC :)

Единственная интересная часть вызова метода заключается в том, что вам нужно указать ему, как найти ключевое свойство через делегат в качестве второго аргумента метода расширения:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
  db.ApplyDetachedPropertyChanges(model, x => x.Id);
  db.SaveChanges();
}

и метода расширения:

public static class EfExtensions
{
  public static void ApplyDetachedPropertyChanges<T>(this ObjectContext db, T entity, Func<T, int> getIdDelegate)
  where T : EntityObject
  {
    var entitySetName = db.DefaultContainerName + "." + entity.GetType().Name;
    var id = getIdDelegate(entity);
    var entityKey = new EntityKey(entitySetName, "Id", id);

    db.Attach(new Department {Id = id, EntityKey = entityKey});
    db.AcceptAllChanges();

    db.ApplyPropertyChanges(entitySetName, entity);
  }
}

Когда метод расширения вызывает AcceptAllChanges, вам нужно быть осторожным при вызове этого, если вы выполняете обновления сразу для нескольких объектов - вы можете легко «потерять» обновления, если не будете осторожны. Следовательно, этот подход действительно подходит только для простых сценариев обновления - например, для множества методов действий MVC :)

Единственная интересная часть вызова метода заключается в том, что вам нужно указать ему, как найти ключевое свойство через делегат в качестве второго аргумента метода расширения:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
  db.ApplyDetachedPropertyChanges(model, x => x.Id);
  db.SaveChanges();
}

и метода расширения:

public static class EfExtensions
{
  public static void ApplyDetachedPropertyChanges<T>(this ObjectContext db, T entity, Func<T, int> getIdDelegate)
  where T : EntityObject
  {
    var entitySetName = db.DefaultContainerName + "." + entity.GetType().Name;
    var id = getIdDelegate(entity);
    var entityKey = new EntityKey(entitySetName, "Id", id);

    db.Attach(new Department {Id = id, EntityKey = entityKey});
    db.AcceptAllChanges();

    db.ApplyPropertyChanges(entitySetName, entity);
  }
}

Когда метод расширения вызывает AcceptAllChanges, вам нужно быть осторожным при вызове этого, если вы выполняете обновления сразу для нескольких объектов - вы можете легко «потерять» обновления, если не будете осторожны. Следовательно, этот подход действительно подходит только для простых сценариев обновления - например, для множества методов действий MVC :)

9
ответ дан 8 December 2019 в 13:02
поделиться
public static class EfExtensions
{
    public static void ApplyDetachedPropertyChanges<T>(this ObjectContext db, T entity, Func<T, int> getIdDelegate)
    where T : EntityObject
    {
        var entitySetName = db.DefaultContainerName + "." + entity.GetType().Name;

        T newEntity = Activator.CreateInstance<T>();
        newEntity.EntityKey = db.CreateEntityKey(entitySetName, entity);

        Type t = typeof(T);
        foreach(EntityKeyMember keyMember in newEntity.EntityKey.EntityKeyValues) {
            PropertyInfo p = t.GetProperty(keyMember.Key);
            p.SetValue(newEntity, keyMember.Value, null);
        }

        db.Attach(newEntity);
        //db.AcceptAllChanges();

        db.ApplyPropertyChanges(entitySetName, entity);
    }
}
4
ответ дан 8 December 2019 в 13:02
поделиться

Попробуйте использовать приведенный ниже код и сообщите мне, работает ли он для вас.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    using (var context =  new EntityContext())
    {
        try
        {
            Object entity = null;
            IEnumerable<KeyValuePair<string, object>> entityKeyValues =
                new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("DepartmentID", id) };

            // Create the  key for a specific SalesOrderHeader object. 
            EntityKey key = new EntityKey("EntityContext.Deparment",   
                                                                   entityKeyValues);

            // Get the object from the context or the persisted store by its key.
            if (context.TryGetObjectByKey(key, out entity))
            {
               context.ApplyPropertyChanges(key.EntitySetName, Model);
               context.SaveChanges();
            }
            else
            {
               // log message if we need
               //"An object with this key could not be found." 
            }                
        }
        catch (EntitySqlException ex)
        {
           // log message
        }
    }
 }       
2
ответ дан 8 December 2019 в 13:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: