代码改变世界

db4o官方入门教程翻译--06.集合和数组

2012-06-27 00:03  于为源  阅读(1157)  评论(1编辑  收藏  举报
.Net方向的关于使用db4o的资料很少,硬着头皮看官方的英文版入门教程。由于英文不太好比较费劲,感觉一定有朋友会遇到相同的问题。所以想将入门教程做一个简单的翻译,水平有限,不太明白的地方可以对照英文版看一下,欢迎您的指正,从第六章随着看有时间就放上一些。欢迎大家交流。 

 

我们将慢慢的向实时的数据处理迈进,首先为我们的车安装传感器并收集他们的输出数据。

using System;
using System.Text;
    
namespace Db4odoc.Tutorial.F1.Chapter4
{   
    public class SensorReadout
    {
        double[] _values;
        DateTime _time;
        Car _car;
        
        public SensorReadout(double[] values, DateTime time, Car car)
        {
            _values = values;
            _time = time;
            _car = car;
        }
        
        public Car Car
        {
            get
            {
                return _car;
            }
        }
        
        public DateTime Time
        {
            get
            {
                return _time;
            }
        }
        
        public int NumValues
        {
            get
            {
                return _values.Length;
            }
        }
        
        public double[] Values
        {
            get
            {
                return _values;
            }
        }
        
        public double GetValue(int idx)
        {
            return _values[idx];
        }
        
        override public string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(_car);
            builder.Append(" : ");
            builder.Append(_time.TimeOfDay);
            builder.Append(" : ");
            for (int i=0; i<_values.Length; ++i)
            {
                if (i > 0)
                {
                    builder.Append(", ");
                }
                builder.Append(_values[i]);
            }
            return builder.ToString();
        }
    }
}

   

在比赛中,汽车可以请求并读取当前的传感器信息,并将它们存储在一个列表中。

using System;
using System.Collections;
    
namespace Db4odoc.Tutorial.F1.Chapter4
{
    public class Car
    {
        string _model;
        Pilot _pilot;
        IList _history;
        
        public Car(string model) : this(model, new ArrayList())
        {
        }
        
        public Car(string model, IList history)
        {
            _model = model;
            _pilot = null;
            _history = history;
        }
        
        public Pilot Pilot
        {
            get
            {
                return _pilot;
            }
            
            set
            {
                _pilot = value;
            }
        }
        
        public string Model
        {
            get
            {
                return _model;
            }
        }
        
        public IList History
        {
            get
            {
                return _history;
            }
        }
        
        public void Snapshot()
        {
            _history.Add(new SensorReadout(Poll(), DateTime.Now, this));
        }
        
        protected double[] Poll()
        {
            int factor = _history.Count + 1;
            return new double[] { 0.1d*factor, 0.2d*factor, 0.3d*factor };
        }
        
        override public string ToString()
        {
            return string.Format("{0}[{1}]/{2}", _model, _pilot, _history.Count);
        }
    }
}

  

我们会限制自己不使用当前的静态数据,并在接下来的章节增加灵活性。

6.1存储

现在,这个应该比较熟悉了。

// storeFirstCar

Car car1 = new Car("Ferrari");

Pilot pilot1 = new Pilot("Michael Schumacher", 100);

car1.Pilot = pilot1;

db.Store(car1);

  

第二辆车在开始时存储两次快照(存储两个传感器读数)。

// storeSecondCar

Pilot pilot2 = new Pilot("Rubens Barrichello", 99);

Car car2 = new Car("BMW");

car2.Pilot = pilot2;

car2.Snapshot();

car2.Snapshot();

db.Store(car2);

  

6.2检索

6.2.1 QBE

首先我们来证实一下确实保存了快照(传感器读数)。

// 读取所有的传感器读数

IObjectSet result = db.QueryByExample(typeof(SensorReadout));

ListResult(result);

  

作为一个原型数组,我们可以提供一个具有相同类型的数组,这个数组中只包含我们需要的数据。

// retrieveSensorReadoutQBE

SensorReadout proto = new SensorReadout(new double[] { 0.3, 0.1 }, DateTime.MinValue, null);

IObjectSet result = db.QueryByExample(proto);

ListResult(result);

  

注意,元素在原型数组中的位置无关紧要。

我们可以根据传感器记录历史来查询相关汽车信息。

// 检索汽车

SensorReadout protoReadout = new SensorReadout(new double[] { 0.6, 0.2 }, DateTime.MinValue, null);

IList protoHistory = new ArrayList();

protoHistory.Add(protoReadout);

Car protoCar = new Car(null, protoHistory);

IObjectSet result = db.QueryByExample(protoCar);

ListResult(result);

  

我们也可以查询集合本身,因为他们是顶级的类对象。

// retrieveCollections

IObjectSet result = db.QueryByExample(new ArrayList());

ListResult(result);

  

但是这种方式并不适用于数组(返回的结果个数是0)。

// 查询数组

IObjectSet result = db.QueryByExample(new double[] { 0.6, 0.4 });

ListResult(result);

  

6.2.2 Native Queries

如果我们想要使用原生查询来查找匹配的SensorReadouts值,我们可以简单地编写如下代码,但这可能会检查每一个实例(遍历所有实例性能上会有损失):

public class RetrieveSensorReadoutPredicate : Predicate

{

    public bool Match(SensorReadout candidate)

    {

        return Array.IndexOf(candidate.Values, 0.3) > -1

            && Array.IndexOf(candidate.Values, 0.1) > -1;

    }

}

  

 

// 原生查询查询传感器读数

IObjectSet results = db.Query(new RetrieveSensorReadoutPredicate());

ListResult(results);

 

下面是根据传感器读数来查找汽车的例子:

public class RetrieveCarPredicate : Predicate

{

    public bool Match(Car car)

    {

        foreach (SensorReadout sensor in car.History)

        {

            if (Array.IndexOf(sensor.Values, 0.3) > -1

                && Array.IndexOf(sensor.Values, 0.1) > -1)

            {

                return true;

            }

        }

        return false;

    }

}

   

// 原生查询

IObjectSet results = db.Query(new RetrieveCarPredicate());

ListResult(results);

   

6.2.3 SODA Query API

使用SODA Query API处理数组和集合的方式与前面的例子很相似。

首先,让我们只查询包含特定值的传感器读数实体。

// retrieveSensorReadoutQuery

IQuery query = db.Query();

query.Constrain(typeof(SensorReadout));

IQuery valueQuery = query.Descend("_values");

valueQuery.Constrain(0.3);

valueQuery.Constrain(0.1);

IObjectSet results = query.Execute();

ListResult(results);

  

下面,我们来查询包含特定传感器读数信息的汽车实体:

// retrieveCarQuery

IQuery query = db.Query();

query.Constrain(typeof(Car));

IQuery historyQuery = query.Descend("_history");

historyQuery.Constrain(typeof(SensorReadout));

IQuery valueQuery = historyQuery.Descend("_values");

valueQuery.Constrain(0.3);

valueQuery.Constrain(0.1);

IObjectSet results = query.Execute();

ListResult(results);

  

 

6.3 Updating and deleting

这个应该是比较熟悉的了,我们只需要注意更新深度就好了:

// updateCar

IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();

config.Common.ObjectClass(typeof(Car)).CascadeOnUpdate(true);

using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))

{

    IObjectSet result = db.QueryByExample(new Car("BMW", null));

    Car car = (Car)result.Next();

    car.Snapshot();

    db.Store(car);

    RetrieveAllSensorReadout(db);

}

  

删除数组和集合对象也没有什么特殊之处。

从数组或集合中中删除一个元素并更新这个数组或集合也是一样没有特殊之处。

// updateCollection

IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();

config.Common.ObjectClass(typeof(Car)).CascadeOnUpdate(true);

using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))

{

    IQuery query = db.Query();

    query.Constrain(typeof (Car));

    IObjectSet result = query.Descend("_history").Execute();

    IList history = (IList) result.Next();

    history.RemoveAt(0);

    db.Store(history);

    Car proto = new Car(null, null);

    result = db.QueryByExample(proto);

    foreach (Car car in result)

    {

        foreach (object readout in car.History)

        {

            Console.WriteLine(readout);

        }

    }

}

   

这个示例还说明Db4o总是能够轻松的访问或修改我们不想看到的内部对象,需要牢记并小心处理。

 

下面我们从数据库中删除所有汽车为下一章做准备。

// deleteAll

IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();

config.Common.ObjectClass(typeof(Car)).CascadeOnDelete(true);

using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))

{

    IObjectSet result = db.QueryByExample(new Car(null, null));

    foreach (object car in result)

    {

        db.Delete(car);

    }

    IObjectSet readouts = db.QueryByExample(new SensorReadout(null, DateTime.MinValue, null));

    foreach (object readout in readouts)

    {

        db.Delete(readout);

    }

}

  

 

6.4. 结论

Ok,集合也是对象。那么为什么我们要具体详细说明集合的所有处理方法呢?这是必要的吗?db4o是怎么处理继承关系的?我们将在下一章讨论这些问题。

 

6.5. Full source

using System;
using System.Collections;
using System.IO;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;
using Db4objects.Db4o.Query;
namespace Db4odoc.Tutorial.F1.Chapter4
{    
    public class CollectionsExample : Util
    {
        readonly static string YapFileName = Path.Combine(
                               Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                               "formula1.yap");  
        
        public static void Main(string[] args)
        {
            File.Delete(YapFileName);
            using(IObjectContainer db = Db4oEmbedded.OpenFile(YapFileName))
            {
                StoreFirstCar(db);
                StoreSecondCar(db);
                RetrieveAllSensorReadout(db);
                RetrieveSensorReadoutQBE(db);
                RetrieveCarQBE(db);
                RetrieveCollections(db);
                RetrieveArrays(db);
                RetrieveSensorReadoutQuery(db);
                RetrieveCarQuery(db);
            };
            UpdateCar();
            UpdateCollection();
            DeleteAll();
            using (IObjectContainer db = Db4oEmbedded.OpenFile(YapFileName))
            {
                RetrieveAllSensorReadout(db);
            }
        }
        
        public static void StoreFirstCar(IObjectContainer db)
        {
            Car car1 = new Car("Ferrari");
            Pilot pilot1 = new Pilot("Michael Schumacher", 100);
            car1.Pilot = pilot1;
            db.Store(car1);
        }
        
        public static void StoreSecondCar(IObjectContainer db)
        {
            Pilot pilot2 = new Pilot("Rubens Barrichello", 99);
            Car car2 = new Car("BMW");
            car2.Pilot = pilot2;
            car2.Snapshot();
            car2.Snapshot();
            db.Store(car2);       
        }
        
        public static void RetrieveAllSensorReadout(IObjectContainer db)
        {
            IObjectSet result = db.QueryByExample(typeof(SensorReadout));
            ListResult(result);
        }
        
        public static void RetrieveSensorReadoutQBE(IObjectContainer db)
        {
            SensorReadout proto = new SensorReadout(new double[] { 0.3, 0.1 }, DateTime.MinValue, null);
            IObjectSet result = db.QueryByExample(proto);
            ListResult(result);
        }
        
        public static void RetrieveCarQBE(IObjectContainer db)
        {
            SensorReadout protoReadout = new SensorReadout(new double[] { 0.6, 0.2 }, DateTime.MinValue, null);
            IList protoHistory = new ArrayList();
            protoHistory.Add(protoReadout);
            Car protoCar = new Car(null, protoHistory);
            IObjectSet result = db.QueryByExample(protoCar);
            ListResult(result);
        }
        
        public static void RetrieveCollections(IObjectContainer db)
        {
            IObjectSet result = db.QueryByExample(new ArrayList());
            ListResult(result);
        }
        
        public static void RetrieveArrays(IObjectContainer db)
        {
            IObjectSet result = db.QueryByExample(new double[] { 0.6, 0.4 });
            ListResult(result);
        }
        
        public static void RetrieveSensorReadoutQuery(IObjectContainer db)
        {
            IQuery query = db.Query();
            query.Constrain(typeof(SensorReadout));
            IQuery valueQuery = query.Descend("_values");
            valueQuery.Constrain(0.3);
            valueQuery.Constrain(0.1);
            IObjectSet results = query.Execute();
            ListResult(results);
        }
        
        public static void RetrieveCarQuery(IObjectContainer db)
        {
            IQuery query = db.Query();
            query.Constrain(typeof(Car));
            IQuery historyQuery = query.Descend("_history");
            historyQuery.Constrain(typeof(SensorReadout));
            IQuery valueQuery = historyQuery.Descend("_values");
            valueQuery.Constrain(0.3);
            valueQuery.Constrain(0.1);
            IObjectSet results = query.Execute();
            ListResult(results);
        }
        public class RetrieveSensorReadoutPredicate : Predicate
        {
            public bool Match(SensorReadout candidate)
            {
                return Array.IndexOf(candidate.Values, 0.3) > -1
                    && Array.IndexOf(candidate.Values, 0.1) > -1;
            }
        }
        
        public static void RetrieveSensorReadoutNative(IObjectContainer db) 
        {
            IObjectSet results = db.Query(new RetrieveSensorReadoutPredicate());
            ListResult(results);
        }
        public class RetrieveCarPredicate : Predicate
        {
            public bool Match(Car car)
            {
                foreach (SensorReadout sensor in car.History)
                {
                    if (Array.IndexOf(sensor.Values, 0.3) > -1
                        && Array.IndexOf(sensor.Values, 0.1) > -1)
                    {
                        return true; 
                    }
                }
                return false;
            }
        }
        public static void RetrieveCarNative(IObjectContainer db)
        {
            IObjectSet results = db.Query(new RetrieveCarPredicate());
            ListResult(results);
        }
        public static void UpdateCar()
        {
            IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();
            config.Common.ObjectClass(typeof(Car)).CascadeOnUpdate(true);
            using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))
            {
                IObjectSet result = db.QueryByExample(new Car("BMW", null));
                Car car = (Car)result.Next();
                car.Snapshot();
                db.Store(car);
                RetrieveAllSensorReadout(db);
            }
        }
        
        public static void UpdateCollection()
        {
            IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();
            config.Common.ObjectClass(typeof(Car)).CascadeOnUpdate(true);
            using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))
            {
                IQuery query = db.Query();
                query.Constrain(typeof (Car));
                IObjectSet result = query.Descend("_history").Execute();
                IList history = (IList) result.Next();
                history.RemoveAt(0);
                db.Store(history);
                Car proto = new Car(null, null);
                result = db.QueryByExample(proto);
                foreach (Car car in result)
                {
                    foreach (object readout in car.History)
                    {
                        Console.WriteLine(readout);
                    }
                }
            }
        }
        
        public static void DeleteAll()
        {
            IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();
            config.Common.ObjectClass(typeof(Car)).CascadeOnDelete(true);
            using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))
            {
                IObjectSet result = db.QueryByExample(new Car(null, null));
                foreach (object car in result)
                {
                    db.Delete(car);
                }
                IObjectSet readouts = db.QueryByExample(new SensorReadout(null, DateTime.MinValue, null));
                foreach (object readout in readouts)
                {
                    db.Delete(readout);
                }
            }
        }
    }
}

  

  相关代码:下载