Query an object but miss out field/Property (Soda)

128 Views Asked by At

I'm trying stuff with db4o since a few days but I got a problem.

Imagine this class just for test:

    class Test
{
  public string TestString
  public int Number;
  public Bitmap Bm;
  public Test2 T2;

}

I'm saving the entire class and all sub-objects. But when I load it, I don't want Bm to be loaded (just leave it null). How can I leave it out? I need to save it because in some cases, I need to load it. It's a performance thing because the pictures are really large.

1

There are 1 best solutions below

0
On

Well, the easiest solution (IMHO) is to wrap the BitMap class in another class and use db4o's transparent activation feature:

using System;
using System.IO;
using System.Linq;
using Db4objects.Db4o;
using Db4objects.Db4o.Activation;
using Db4objects.Db4o.TA;

namespace ActivationDepth
{
    class Program
    {
        static void Main(string[] args)
        {
            var dbFilePath = Path.GetTempFileName();
            using (var db = Db4oEmbedded.OpenFile(dbFilePath))
            {
                db.Store(new C1 { Name = "c1", Huge = new MyHugeClass("I am really huge....")});
            }

            var config = Db4oEmbedded.NewConfiguration();
            config.Common.Add(new TransparentActivationSupport());
            config.Common.ActivationDepth = 0;
            using (var db = Db4oEmbedded.OpenFile(config, dbFilePath))
            {
                var item = db.Query<C1>().ElementAt(0);

                Console.WriteLine("{0}", db.Ext().IsActive(item));
                Console.WriteLine("[Huge] {0} : {1}", db.Ext().IsActive(item.huge), item.huge);
                Console.WriteLine("[Huge] {0} : {1}", db.Ext().IsActive(item.Huge), item.Huge);
            }
        }
    }

    class C1 : IActivatable
    {
        public string Name
        {
            get
            {
                Activate(ActivationPurpose.Read);
                return name;
            }

            set
            {
                Activate(ActivationPurpose.Write);
                name = value;
            }
        }

        public MyHugeClass Huge
        {
            get
            {
                Activate(ActivationPurpose.Read);
                return huge;
            }

            set
            {
                Activate(ActivationPurpose.Write);
                huge = value;
            }
        }

        public override string ToString()
        {
            Activate(ActivationPurpose.Read);
            return string.Format("[{0}] {1}", GetType().Name, name);
        }

        public void Bind(IActivator activator)
        {
            if (this.activator != null && activator != null)
            {
                throw new Exception("activation already set");
            }

            this.activator = activator;
        }

        public void Activate(ActivationPurpose purpose)
        {
            if (activator != null)
            {
                activator.Activate(purpose);
            }
        }

        public MyHugeClass huge;
        private string name;

        [NonSerialized]
        private IActivator activator;
    }

    class MyHugeClass : IActivatable
    {
        public string Name
        {
            get
            {
                Activate(ActivationPurpose.Read);
                return name;
            }

            set
            {
                Activate(ActivationPurpose.Write);
                name = value;
            }
        }

        public MyHugeClass(string name)
        {
            this.name = name;
        }

        public override string ToString()
        {
            Activate(ActivationPurpose.Read);
            return string.Format("[{0}] {1}", GetType().Name, name);
        }

        public void Bind(IActivator activator)
        {
            if (this.activator != null && activator != null)
            {
                throw new Exception("activation already set");
            }

            this.activator = activator;
        }

        public void Activate(ActivationPurpose purpose)
        {
            if (activator != null)
            {
                activator.Activate(purpose);
            }
        }

        private string name;

        [NonSerialized]
        private IActivator activator;
    }
}

Note that even though I have implemented the IActivatable interface manually I don't recommend that; you can use db4otool to implement it for you automatically.

Another possible solution is to control activation for your type (when an object is not activated in db4o, its reference is valid but all of its fields will be not initialized taking no space whatsoever).

For instance you can do something like:

using System;
using System.IO;
using System.Linq;
using Db4objects.Db4o;
using Db4objects.Db4o.Events;

namespace ActivationDepth
{
    class Program
    {
        static void Main(string[] args)
        {
            var dbFilePath = Path.GetTempFileName();
            using (var db = Db4oEmbedded.OpenFile(dbFilePath))
            {
                db.Store(new C1 { name = "c1", c2 = new C2("c2"), huge = new MyHugeClass("I am really huge....")});
            }

            var config = Db4oEmbedded.NewConfiguration();
            using (var db = Db4oEmbedded.OpenFile(config, dbFilePath))
            {
                var activate = false;
                var fac = EventRegistryFactory.ForObjectContainer(db);
                fac.Activating += (sender, eventArgs) =>
                {
                    if (!activate && eventArgs.Object.GetType() == typeof(MyHugeClass))
                    {
                        Console.WriteLine("[{0}] Ignoring activation.", eventArgs.Object);
                        eventArgs.Cancel();
                    }
                    else
                    {
                        Console.WriteLine("[{0}] Activation will proceed.", eventArgs.Object);
                    }
                };

                var item = db.Query<C1>().ElementAt(0);
                Console.WriteLine("[IsActive] {0}", db.Ext().IsActive(item.huge));
                activate = true;
                db.Activate(item.huge, 3);
                Console.WriteLine("[IsActive] {0}", db.Ext().IsActive(item.huge));
            }
        }
    }

    class C1
    {
        public string name;
        public C2 c2;
        public MyHugeClass huge;

        public override string ToString()
        {
            return string.Format("[{0}] {1}", GetType().Name, name);
        }
    }

    class C2
    {
        public string name;

        public C2(string name)
        {
            this.name = name;
        }

        public override string ToString()
        {
            return string.Format("[{0}] {1}", GetType().Name, name);
        }
    }

    class MyHugeClass
    {
        public string text;

        public MyHugeClass(string text)
        {
            this.text = text;
        }

        public override string ToString()
        {
            return string.Format("[{0}] {1}", GetType().Name, text);
        }
    }
}

You can also play with activation depth.

Hope this help.