Search code examples
db4o

db4o Transparent Persistence Not Working


Using db4o client/server, updates are not working for collection properties of an object. I'm using transparent persistence, but that's not helping. Then, I changed my Collection property to ActivatableCollection, but no luck.

This is the server setup:

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

This is the entity that I want to save:

public class Application : ActivatableEntity

And this is the property within the Application entity:

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

This is the client code to update each object within the 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);

Curiously, db.Commit() didn't work either.

There are two work-arounds, but I'd rather do this the "right" way.

Work-around 1: Call db.Store(task) on each task as the change is made.

Work-around 2: Before calling db.Store(), do this:

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

Can anyone tell me why the list isn't updating?

If it helps, here is the ActivatableCollection class:

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

}


Solution

  • I was able to get transparent activation and persistence to work. I decided not to go with the approach for the reasons mentioned in my comment above. I think the easiest way to handle cascading updates is to simply use a client config like this:

    IClientConfiguration clientConfig = Db4oClientServer.NewClientConfiguration();
    

    And then either a bunch of these (this isn't so bad because we can add an attribute to every domain entity, then reflectively do this on each one):

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

    Or this:

    clientConfig.Common.UpdateDepth = 10;
    
    return Db4oClientServer.OpenClient(clientConfig, databaseServerName, databaseServerPort, databaseUser, databasePassword);
    

    Now, here is the server config that allowed me to get transparent persistence working.

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

    Hope this helps someone.