2011-12-04 5 views
0

Avec le client/serveur db4o, les mises à jour ne fonctionnent pas pour les propriétés de collection d'un objet. J'utilise la persistance transparente, mais cela n'aide pas. Ensuite, j'ai changé ma propriété Collection en ActivatableCollection, mais pas de chance.db4o La persistance transparente ne fonctionne pas

C'est la configuration du serveur:

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); 
} 

Ceci est l'entité que je veux sauver:

public class Application : ActivatableEntity 

Et c'est la propriété de l'entité d'application:

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

Il s'agit du code client pour mettre à jour chaque objet de la collection:

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); 

Curieusement, db.Commit() ne fonctionnait pas non plus.

Il y a deux solutions, mais je préfère faire cela de la «bonne» manière. Contournement 1: Appelez db.Store (tâche) sur chaque tâche à mesure que la modification est effectuée.

travail autour de 2: Avant d'appeler db.Store(), faites ceci:

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

Quelqu'un peut-il me dire pourquoi la liste est mise à jour ne pas?

Si elle aide, voici la classe 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

Grâce à beaucoup d'essais et d'erreurs, et à RTFM, je progresse lentement. J'ai découvert que je n'utilisais pas la persistance transparente. Il semble que la configuration du serveur et du client nécessite la configuration TransparentPersistenceSupport. Et j'ai manqué où je dois appeler activer ON TOUS GETTER ET SETTER DANS CHAQUE ENTITÉ. Pas très transparent ... –

+0

Cela signifie que je dois implémenter des getters manuels et des setters pour chaque propriété. Les entités de domaine ne devraient rien savoir de la couche de persistance, mais cette approche a du code db4o sur toutes les entités. Il peut être plus facile de sauvegarder chaque objet explicitement. Je le ferais si je pouvais comprendre pourquoi l'ajout d'un nouvel objet à une liste existante ne conserve pas l'association entre l'objet et l'objet parent. Par exemple: Foo a la propriété Liste . Quand je fais Bars.Add (new Bar()), la nouvelle barre est stockée mais elle n'est pas associée à Foo. –

Répondre

0

Je suis en mesure d'obtenir une activation transparente et de la persévérance au travail. J'ai décidé de ne pas aller avec l'approche pour les raisons mentionnées dans mon commentaire ci-dessus. Je pense que la meilleure façon de gérer les mises à jour en cascade est d'utiliser simplement comme config client ceci:

IClientConfiguration clientConfig = Db4oClientServer.NewClientConfiguration(); 

Et puis soit un groupe d'entre eux (ce n'est pas si mal parce que nous pouvons ajouter un attribut à chaque entité de domaine , puis faire ce pensivement sur chacun):

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

Ou ceci:

clientConfig.Common.UpdateDepth = 10; 

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

maintenant, voici la configuration du serveur qui m'a permis de travailler la persistance transparente.

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); 
} 

Espérons que cela aide quelqu'un.

2

En effet, la persistance transparente nécessite un appel à son activateur avant chaque accès au champ. Cependant, les intentions sont que vous le fassiez avec le enhancer-tool au lieu de l'implémenter manuellement.

Une autre remarque: lorsque vous utilisez CascadeOnUpdate (true) partout où db4o va stocker tous les objets activés accessibles. Si le graphe d'objets est énorme, cela peut être un goulot d'étranglement majeur.

0

J'ai eu le même problème avec Transparent Activation et Persistence dans java. J'ai réussi à le faire fonctionner nettoyer la base de données et à partir de zéro. Cependant, ne fonctionne pas en appelant commit() après avoir modifié le graphe d'objet. Vous devez appeler store() sur l'objet racine. Ceci est un exemple simple:

/*************** 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(); 
    } 
} 
Questions connexes