db4o透明持久性不起作用

时间:2011-12-04 18:23:19

标签: db4o

使用db4o客户端/服务器,更新不适用于对象的集合属性。我正在使用透明持久性,但这没有帮助。然后,我将Collection属性更改为ActivatableCollection,但没有运气。

这是服务器设置:

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

}

3 个答案:

答案 0 :(得分:2)

实际上,透明持久性需要在每次访问字段之前调用它的激活器。但是,您的意图是使用enhancer-tool而不是手动实现。

另一个注意事项:当您使用CascadeOnUpdate(true)时,db4o将最终存储每个可访问的激活对象。如果对象图很大,这可能是一个主要的性能瓶颈。

答案 1 :(得分: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 :(得分: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();
    }
}