他的地址: http://www.cnblogs.com/JackyXu/archive/2006/11/10/556689.html(五)
http://www.cnblogs.com/JackyXu/archive/2006/11/10/557168.html(四)
http://www.cnblogs.com/JackyXu/archive/2006/11/10/557168.html(三)
http://www.cnblogs.com/JackyXu/archive/2006/11/13/559747.html(二)
http://www.cnblogs.com/JackyXu/archive/2006/11/13/559747.html(一)
4.3更新结构化对象
要更新db4o的结构化对象,只需要调用Set()方法。
IObjectSet result = db.Get( new Car( " Ferrari " ));
Car found = (Car)result.Next();
found.Pilot = new Pilot( " Somebody else " , 0 );
db.Set(found);
result = db.Get( new Car( " Ferrari " ));
ListResult(result);
IObjectSet result = db.Get( new Car( " Ferrari " ));
Car found = (Car)result.Next();
found.Pilot.AddPoints( 1 );
db.Set(found);
result = db.Get( new Car( " Ferrari " ));
ListResult(result);
首先,我们先修改Pilot,然后再修改他的Car
IObjectSet result = db.Get( new Car( " Ferrari " ));
Car found = (Car)result.Next();
found.Pilot.AddPoints( 1 );
db.Set(found);
IObjectSet result = db.Get( new Car( " Ferrari " ));
ListResult(result);
4.3.1. 更新深度
想象一下,假如一个类包含很多子类,子类也包含子类。那么,当你修改这个类的对象的时候,要跟着一起更新很多类:他的子类、孙子类。。。。这样,无疑是低效率的。
所以,在刚才更新的步骤中,我们修改了Pilot的子类--Car。当我们保存修改时,我们叫db4o保存我们的Car对象,就认为db4o还帮我们修改了Pilot。但是,我们刚刚的修改程序和第一个修改程序一样,为什么第一次的修改程序可以真正修改到Pilot?第一次,我们修改后,db4o不会真正的获取修改的Pilot,他只是修改了内存中的同样的一个Pilot,而没有更新入数据库。其实我们看到的修改后的值是一个假象而已。重新运行程序,就会发现修改已经不存在了。
为了灵活的解决这个问题,db4o引进了“更新深度”这个概念,这个概念用来控制对一个对象成员树我们到底更新几层。默认值为1,表示只有原始的String型的变量被更新,而对内部引用的对象不做更新。
db4o让更新在一个“度”的范围内,不会过分,也不会浪费效率。但是我们现在想做的是让db4o更新整个Car的对象,而不是只更新一层。
Db4oFactory.Configure().ObjectClass( typeof (Car))
.CascadeOnUpdate( true );
IObjectSet result = db.Get( new Car( " Ferrari " ));
Car found = (Car)result.Next();
found.Pilot.AddPoints( 1 );
db.Set(found);
IObjectSet result = db.Get( new Car( " Ferrari " ));
ListResult(result);
看起来好多了!
注意:设置更新深度的动作一定要写在db4o的Open()之前。
我们将会在以后的章节讲到db4o的更新深度、其他的复杂对象的重点,和各自db4o设置细节。
4.4. 删除结构化对象
就像我们之前用到的,Delete()方法可以删除一个对象。
IObjectSet result = db.Get( new Car( " Ferrari " ));
Car found = (Car)result.Next();
db.Delete(found);
result = db.Get( new Car( null ));
ListResult(result);
很好,Car已经被删除了,那Pilot呢?
Pilot proto = new Pilot( null , 0 );
IObjectSet result = db.Get(proto);
ListResult(result);
4.4.1. 循环删除
哈哈,你已经在猜想,是不是循环删除和循环更新很像呢?对了,让我们来设置db4o的删除深度。
Db4oFactory.Configure().ObjectClass( typeof (Car))
.CascadeOnDelete( true );
IObjectSet result = db.Get( new Car( " BMW " ));
Car found = (Car)result.Next();
db.Delete(found);
result = db.Get( new Car( null ));
ListResult(result);
再次注意:所有的设置都不需在IObjectContainer 打开之前
让我们来看一下Pilot:
Pilot proto = new Pilot( null , 0 );
IObjectSet result = db.Get(proto);
ListResult(result);
4.4.2. 再次回顾循环删除
问题--如果孩子对象被删除了,但是这个孩子还有被其他对象引用怎么办?
IObjectSet result = db.Get( new Pilot( " Michael Schumacher " , 0 ));
Pilot pilot = (Pilot)result.Next();
Car car1 = new Car( " Ferrari " );
Car car2 = new Car( " BMW " );
car1.Pilot = pilot;
car2.Pilot = pilot;
db.Set(car1);
db.Set(car2);
db.Delete(car2);
result = db.Get( new Car( null ));
ListResult(result);
Pilot proto = new Pilot( null , 0 );
IObjectSet result = db.Get(proto);
ListResult(result);
我们有一个问题了:手边没有合适的解决方案。db4o在删除一个对象的时候,不会去检查是不是有别的对象引用了它,所以呢,要十分小心。
让我们在进入下一章以前清理一下数据库
IObjectSet result = db.Get( typeof (Object));
foreach ( object item in result)
{
db.Delete(item);
}
4.5. 总结
对象之间的关系有如下内容:我们可以钩住一个根对象,找到它的引用图,制定查询。但是当某个对象里面有像数组、集合等的多值成员的时候该怎么办?见下一章
4.6. Full source
using System.IO;
using Db4objects.Db4o;
using Db4objects.Db4o.Query;
namespace Db4objects.Db4o.Tutorial.F1.Chapter2
{
public class StructuredExample : Util
{
public static void Main(String[] args)
{
File.Delete(Util.YapFileName);
IObjectContainer db = Db4oFactory.OpenFile(Util.YapFileName);
try
{
StoreFirstCar(db);
StoreSecondCar(db);
RetrieveAllCarsQBE(db);
RetrieveAllPilotsQBE(db);
RetrieveCarByPilotQBE(db);
RetrieveCarByPilotNameQuery(db);
RetrieveCarByPilotProtoQuery(db);
RetrievePilotByCarModelQuery(db);
UpdateCar(db);
UpdatePilotSingleSession(db);
UpdatePilotSeparateSessionsPart1(db);
db.Close();
db=Db4oFactory.OpenFile(Util.YapFileName);
UpdatePilotSeparateSessionsPart2(db);
db.Close();
UpdatePilotSeparateSessionsImprovedPart1(db);
db=Db4oFactory.OpenFile(Util.YapFileName);
UpdatePilotSeparateSessionsImprovedPart2(db);
db.Close();
db=Db4oFactory.OpenFile(Util.YapFileName);
UpdatePilotSeparateSessionsImprovedPart3(db);
DeleteFlat(db);
db.Close();
DeleteDeepPart1(db);
db=Db4oFactory.OpenFile(Util.YapFileName);
DeleteDeepPart2(db);
DeleteDeepRevisited(db);
}
finally
{
db.Close();
}
}
public static void StoreFirstCar(IObjectContainer db)
{
Car car1 = new Car("Ferrari");
Pilot pilot1 = new Pilot("Michael Schumacher", 100);
car1.Pilot = pilot1;
db.Set(car1);
}
public static void StoreSecondCar(IObjectContainer db)
{
Pilot pilot2 = new Pilot("Rubens Barrichello", 99);
db.Set(pilot2);
Car car2 = new Car("BMW");
car2.Pilot = pilot2;
db.Set(car2);
}
public static void RetrieveAllCarsQBE(IObjectContainer db)
{
Car proto = new Car(null);
IObjectSet result = db.Get(proto);
ListResult(result);
}
public static void RetrieveAllPilotsQBE(IObjectContainer db)
{
Pilot proto = new Pilot(null, 0);
IObjectSet result = db.Get(proto);
ListResult(result);
}
public static void RetrieveCarByPilotQBE(IObjectContainer db)
{
Pilot pilotproto = new Pilot("Rubens Barrichello",0);
Car carproto = new Car(null);
carproto.Pilot = pilotproto;
IObjectSet result = db.Get(carproto);
ListResult(result);
}
public static void RetrieveCarByPilotNameQuery(IObjectContainer db)
{
IQuery query = db.Query();
query.Constrain(typeof(Car));
query.Descend("_pilot").Descend("_name")
.Constrain("Rubens Barrichello");
IObjectSet result = query.Execute();
ListResult(result);
}
public static void RetrieveCarByPilotProtoQuery(IObjectContainer db)
{
IQuery query = db.Query();
query.Constrain(typeof(Car));
Pilot proto = new Pilot("Rubens Barrichello", 0);
query.Descend("_pilot").Constrain(proto);
IObjectSet result = query.Execute();
ListResult(result);
}
public static void RetrievePilotByCarModelQuery(IObjectContainer db)
{
IQuery carQuery = db.Query();
carQuery.Constrain(typeof(Car));
carQuery.Descend("_model").Constrain("Ferrari");
IQuery pilotQuery = carQuery.Descend("_pilot");
IObjectSet result = pilotQuery.Execute();
ListResult(result);
}
public static void RetrieveAllPilots(IObjectContainer db)
{
IObjectSet results = db.Get(typeof(Pilot));
ListResult(results);
}
public static void RetrieveAllCars(IObjectContainer db)
{
IObjectSet results = db.Get(typeof(Car));
ListResult(results);
}
public class RetrieveCarsByPilotNamePredicate : Predicate
{
readonly string _pilotName;
public RetrieveCarsByPilotNamePredicate(string pilotName)
{
_pilotName = pilotName;
}
public bool Match(Car candidate)
{
return candidate.Pilot.Name == _pilotName;
}
}
public static void RetrieveCarsByPilotNameNative(IObjectContainer db)
{
string pilotName = "Rubens Barrichello";
IObjectSet results = db.Query(new RetrieveCarsByPilotNamePredicate(pilotName));
ListResult(results);
}
public static void UpdateCar(IObjectContainer db)
{
IObjectSet result = db.Get(new Car("Ferrari"));
Car found = (Car)result.Next();
found.Pilot = new Pilot("Somebody else", 0);
db.Set(found);
result = db.Get(new Car("Ferrari"));
ListResult(result);
}
public static void UpdatePilotSingleSession(IObjectContainer db)
{
IObjectSet result = db.Get(new Car("Ferrari"));
Car found = (Car)result.Next();
found.Pilot.AddPoints(1);
db.Set(found);
result = db.Get(new Car("Ferrari"));
ListResult(result);
}
public static void UpdatePilotSeparateSessionsPart1(IObjectContainer db)
{
IObjectSet result = db.Get(new Car("Ferrari"));
Car found = (Car)result.Next();
found.Pilot.AddPoints(1);
db.Set(found);
}
public static void UpdatePilotSeparateSessionsPart2(IObjectContainer db)
{
IObjectSet result = db.Get(new Car("Ferrari"));
ListResult(result);
}
public static void UpdatePilotSeparateSessionsImprovedPart1(IObjectContainer db)
{
Db4oFactory.Configure().ObjectClass(typeof(Car))
.CascadeOnUpdate(true);
}
public static void UpdatePilotSeparateSessionsImprovedPart2(IObjectContainer db)
{
IObjectSet result = db.Get(new Car("Ferrari"));
Car found = (Car)result.Next();
found.Pilot.AddPoints(1);
db.Set(found);
}
public static void UpdatePilotSeparateSessionsImprovedPart3(IObjectContainer db)
{
IObjectSet result = db.Get(new Car("Ferrari"));
ListResult(result);
}
public static void DeleteFlat(IObjectContainer db)
{
IObjectSet result = db.Get(new Car("Ferrari"));
Car found = (Car)result.Next();
db.Delete(found);
result = db.Get(new Car(null));
ListResult(result);
}
public static void DeleteDeepPart1(IObjectContainer db)
{
Db4oFactory.Configure().ObjectClass(typeof(Car))
.CascadeOnDelete(true);
}
public static void DeleteDeepPart2(IObjectContainer db)
{
IObjectSet result = db.Get(new Car("BMW"));
Car found = (Car)result.Next();
db.Delete(found);
result = db.Get(new Car(null));
ListResult(result);
}
public static void DeleteDeepRevisited(IObjectContainer db)
{
IObjectSet result = db.Get(new Pilot("Michael Schumacher", 0));
Pilot pilot = (Pilot)result.Next();
Car car1 = new Car("Ferrari");
Car car2 = new Car("BMW");
car1.Pilot = pilot;
car2.Pilot = pilot;
db.Set(car1);
db.Set(car2);
db.Delete(car2);
result = db.Get(new Car(null));
ListResult(result);
}
}
}