2011-12-04 21 views
0

Используя клиент/сервер db4o, обновления не работают для свойств коллекции объекта. Я использую прозрачную настойчивость, но это не помогает. Затем я изменил свойство Collection на ActivatableCollection, но не повезло.db4o Прозрачная устойчивость не работает

Это настройка сервера:

private void StartDatabase() 
{ 
    IServerConfiguration serverConfiguration = Db4oClientServer.NewServerConfiguration(); 

    serverConfiguration.Networking.MessageRecipient = this; 

    serverConfiguration.Common.Add(new TransparentActivationSupport()); 
    serverConfiguration.Common.Add(new TransparentPersistenceSupport()); 

    string db4oDatabasePath  = AppDomain.CurrentDomain.BaseDirectory; 
    string db4oDatabaseFileName = ConfigurationManager.AppSettings["db4oDatabaseFileName"];    
    int databaseServerPort  = Convert.ToInt32(ConfigurationManager.AppSettings["databaseServerPort"], CultureInfo.InvariantCulture); 

    _db4oServer = Db4oClientServer.OpenServer(serverConfiguration, db4oDatabasePath + db4oDatabaseFileName, databaseServerPort); 

    string databaseUser  = ConfigurationManager.AppSettings["databaseUser"]; 
    string databasePassword = ConfigurationManager.AppSettings["databasePassword"]; 

    _db4oServer.GrantAccess(databaseUser, databasePassword); 
} 

Это объект, который я хочу сохранить:

public class Application : ActivatableEntity 

И это свойство внутри объекта Application:

public ActivatableCollection<TaskBase> Tasks { get; private set; } 

Это код клиента для обновления каждого объекта в коллекции:

Application application = (from Application app in db 
             where app.Name == "Foo" 
             select app).FirstOrDefault(); 

      foreach (TaskBase task in application.Tasks) 
      { 
       task.Description += "."; 
      } 

      db.Store(application); 

Любопытно, что db.Commit() также не работал.

Есть два обхода, но я предпочел бы сделать это «правильным» способом.

Работать вокруг 1: вызывать db.Store (задача) для каждой задачи по мере внесения изменения.

Работа вокруг 2: Перед вызовом db.Store(), сделайте следующее:

db.Ext().Configure().UpdateDepth(5); 

Может кто-нибудь сказать мне, почему список не обновляется?

Если это помогает, вот это класс ActivatableCollection:

public class ActivatableCollection<T> : Collection<T>, IActivatable 

{ 
    [Transient] 
    private IActivator _activator; 

/// <summary> 
/// Activates the specified purpose. 
/// </summary> 
/// <param name="purpose">The purpose.</param> 
public void Activate(ActivationPurpose purpose) 
{ 
    if (this._activator != null) 
    { 
     this._activator.Activate(purpose); 
    } 
} 

/// <summary> 
/// Binds the specified activator. 
/// </summary> 
/// <param name="activator">The activator.</param> 
public void Bind(IActivator activator) 
{ 
    if (_activator == activator) { return; } 

    if (activator != null && null != _activator) { throw new System.InvalidOperationException(); } 

    _activator = activator; 
} 

}

+0

Через много проб и ошибок и RTFM, я делаю медленный прогресс. Я узнал, что не использовал прозрачную настойчивость. Похоже, что для конфигурации сервера и клиента требуется конфигурация TransparentPersistenceSupport. И я пропустил, где мне нужно активировать ВКЛЮЧЕНИЕ КАЖДОГО ПОЛУЧЕНИЯ И УСТАНОВКИ В КАЖДОЙ ЛИНИИ. Не очень прозрачно ... –

+0

Это означает, что я должен внедрять ручные геттеры и сеттеры для каждого свойства. Сущности домена не должны ничего знать о уровне персистентности, но этот подход имеет код db4o по всему объекту. Может быть проще просто сохранить каждый объект явно. Я бы сделал это, если бы мог понять, почему добавление нового объекта в существующий список не поддерживает связь между объектом и родительским объектом. Например: Foo имеет свойство List . Когда я делаю Bars.Add (новый Bar()), новый Bar сохраняется, но он не связан с Foo. –

ответ

0

Я был в состоянии получить прозрачную активацию и настойчивость, чтобы работать. Я решил не идти с подходом к причинам, упомянутым в моем комментарии выше. Я думаю, что самый простой способ справиться с каскадными обновлениями, чтобы просто использовать конфигурацию клиента, как это:

IClientConfiguration clientConfig = Db4oClientServer.NewClientConfiguration(); 

, а затем либо связку из них (это не так плохо, потому что мы можем добавить атрибут каждого домен объект , то рефлекторно сделать это на каждом из них):

clientConfig.Common.ObjectClass(typeof(Application)).CascadeOnUpdate(true); 

Или это:

clientConfig.Common.UpdateDepth = 10; 

return Db4oClientServer.OpenClient(clientConfig, databaseServerName, databaseServerPort, databaseUser, databasePassword); 

Теперь, вот сервер конфигурации, что позволило мне получить прозрачный настойчивость работать.

private void StartDatabase() 
{ 
    IServerConfiguration serverConfiguration = Db4oClientServer.NewServerConfiguration(); 

    serverConfiguration.Networking.MessageRecipient = this; 

    serverConfiguration.Common.Add(new TransparentActivationSupport()); 
    serverConfiguration.Common.Add(new TransparentPersistenceSupport()); 

    string db4oDatabasePath  = AppDomain.CurrentDomain.BaseDirectory; 
    string db4oDatabaseFileName = ConfigurationManager.AppSettings["db4oDatabaseFileName"];    
    int databaseServerPort  = Convert.ToInt32(ConfigurationManager.AppSettings["databaseServerPort"], CultureInfo.InvariantCulture); 

    _db4oServer = Db4oClientServer.OpenServer(serverConfiguration, db4oDatabasePath + db4oDatabaseFileName, databaseServerPort); 

    string databaseUser  = ConfigurationManager.AppSettings["databaseUser"]; 
    string databasePassword = ConfigurationManager.AppSettings["databasePassword"]; 

    _db4oServer.GrantAccess(databaseUser, databasePassword); 
} 

Надеюсь, это поможет кому-то.

2

Действительно, прозрачная настойчивость требует вызова ее активатора перед каждым доступом к полю. Однако намерения состоят в том, что вы делаете это с помощью enhancer-tool вместо выполнения вручную.

Другое примечание. Когда вы используете CascadeOnUpdate (true), везде db4o в конечном итоге будет хранить каждый доступный активированный объект. Если объектный график огромен, это может быть крупная бутылочная горловина.

0

У меня была та же проблема с прозрачной активацией и сохранением в java. Мне удалось заставить его работать с очисткой базы данных и начать с нуля. Тем не менее, никакие работы, вызвав commit() после изменения графа объекта. Вы должны вызвать store() для корневого объекта. Это простой пример:

/*************** Item.java ******************************************/ 
import com.db4o.activation.ActivationPurpose; 
import com.db4o.activation.Activator; 
import com.db4o.collections.ActivatableSupport; 
import com.db4o.ta.Activatable; 

public class Item implements Activatable { 

    private String name; 
    private transient Activator activator; 

    public Item(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     activate(ActivationPurpose.READ); 
     return name; 
    } 

    public void setName(String name) { 
     activate(ActivationPurpose.WRITE); 
     this.name = name; 
    } 

    @Override 
    public String toString() { 
     activate(ActivationPurpose.READ); 
     return "Item [name=" + name + "]"; 
    } 

    public void activate(ActivationPurpose purpose) { 
     ActivatableSupport.activate(this.activator, purpose); 
    } 

    public void bind(Activator activator) { 
     this.activator = ActivatableSupport.validateForBind(this.activator, activator); 
    } 
} 


/******************* Container.java *********************************/ 
import java.util.Set; 
import com.db4o.activation.ActivationPurpose; 
import com.db4o.activation.Activator; 
import com.db4o.collections.ActivatableHashSet; 
import com.db4o.collections.ActivatableSupport; 
import com.db4o.ta.Activatable; 

public class Container implements Activatable { 

    private String name; 
    private Set<Item> items; 
    private transient Activator activator; 

    public Container() { 
     items = new ActivatableHashSet<Item>(); 
    } 

    public String getName() { 
     activate(ActivationPurpose.READ); 
     return name; 
    } 

    public void setName(String name) { 
     activate(ActivationPurpose.WRITE); 
     this.name = name; 
    } 

    public void addItem(Item item) { 
     activate(ActivationPurpose.WRITE); 
     items.add(item); 
    } 
    public Set<Item> getItems() { 
     activate(ActivationPurpose.READ); 
     return items; 
    } 

    @Override 
    public String toString() { 
     activate(ActivationPurpose.READ); 
     return "Container [items=" + items + "]"; 
    } 

    public void activate(ActivationPurpose purpose) { 
     ActivatableSupport.activate(this.activator, purpose); 
    } 

    public void bind(Activator activator) { 
     this.activator = ctivatableSupport.validateForBind(this.activator, activator); 
    } 
} 

/************* Main.java ********************************************/ 
import com.db4o.Db4oEmbedded; 
import com.db4o.ObjectContainer; 
import com.db4o.ObjectSet; 
import com.db4o.config.EmbeddedConfiguration; 
import com.db4o.ta.TransparentActivationSupport; 
import com.db4o.ta.TransparentPersistenceSupport; 

public class Main { 

    public static void main() { 
     EmbeddedConfiguration config = Db4oEmbedded.newConfiguration(); 
     config.common().add(new TransparentActivationSupport()); 
     config.common().add(new TransparentPersistenceSupport()); 
     ObjectContainer db = Db4oEmbedded.openFile(config, System.getProperty("user.home") + "/testTP.db4o"); 

     Container c = new Container(); 
     c.setName("Container0"); 
     ObjectSet<Container> result = db.queryByExample(c); 
     if(result.hasNext()) { 
      c = result.next(); 
      System.out.println(c); 
     } 
     c.addItem(new Item("Item" + c.getItems().size())); 
     db.store(c); 
     System.out.println(c); 
     db.close(); 
    } 
}