【问题标题】:db4o Transparent Persistence Not Workingdb4o 透明持久性不起作用
【发布时间】:2011-12-04 18:23:18
【问题描述】:

使用 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(task)。

解决方法 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;
}

}

【问题讨论】:

  • 经过大量的反复试验和 RTFM,我进展缓慢。我发现我没有使用透明持久性。看来服务器和客户端配置需要TransparentPersistenceSupport 配置。而且我错过了必须在每个实体中的每个 GETTER 和 SETTER 上调用激活的地方。不是很透明...
  • 这样做意味着我必须为每个属性实现手动获取器和设置器。域实体应该对持久层一无所知,但是这种方法在每个实体上都有 db4o 代码。显式保存每个对象可能更容易。如果我能弄清楚为什么将新对象添加到现有列表不会保持对象和父对象之间的关联,我会这样做。例如:Foo 具有属性 List。当我执行 Bars.Add(new Bar()) 时,新 Bar 被存储,但它与 Foo 无关。

标签: db4o


【解决方案1】:

确实,透明持久性需要在每次访问字段之前调用它的激活器。然而,目的是您使用 enhancer-tool 执行此操作,而不是手动实现。

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

【讨论】:

    【解决方案2】:

    我能够获得透明的激活和持久性工作。由于我上面评论中提到的原因,我决定不采用这种方法。我认为处理级联更新的最简单方法是简单地使用这样的客户端配置:

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

    希望这对某人有所帮助。

    【讨论】:

      【解决方案3】:

      我在 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();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多