我不知道这是我的错误还是Devexpres XPO中的错误? (版本12.1.5)
看看下面的示例:
static void Main(string[] args)
{
var dxs = Session.DefaultSession;
var sw = new Stopwatch();
using (var uow = dxs.BeginNestedUnitOfWork())
{
var dbp = new DBParent(uow) { TitleXX = "Morgan" };
// add 1000 child to the parent table
for (var i = 0; i < 1000; i++)
{
var dbc = new DBChild(uow)
{
Name = string.Format("Child {0}", i),
Parent = dbp
};
}
var count = uow.GetObjectsToSave();
// count = 1001
sw.Start();
uow.CommitChanges();
sw.Stop();
Console.WriteLine("Time:" +sw.Elapsed);
// Takes about 7 sec
}
using (var uow = dxs.BeginNestedUnitOfWork())
{
var dbp = new XPCollection<DBParent>(uow).First();
dbp.TitleXX = "Another title";
dbp.Save();
var count = uow.GetObjectsToSave();
// count = 1
sw.Reset();
sw.Start();
uow.CommitChanges();
sw.Stop();
Console.WriteLine("Time:" + sw.Elapsed); // Takes about 4 sec ????
}
Console.ReadLine();
}
}
这是我的对象:
public class DBParent : XPObject
{
public DBParent(){}
public DBParent(Session session) : base(session) { }
private string _TitleXX;
public string TitleXX
{
get { return _TitleXX; }
set { SetPropertyValue("TitleXX", ref _TitleXX, value); }
}
[Association("a1"), Aggregated]
public XPCollection<DBChild> Childs
{
get
{
return GetCollection<DBChild>("Childs");
}
}
}
public class DBChild : XPObject
{
public DBChild(){}
public DBChild(Session session): base(session){}
private string _Name;
public string Name
{
get { return _Name; }
set { SetPropertyValue("Name", ref _Name, value); }
}
private DBParent _Parent;
[Association("a1")]
public DBParent Parent
{
get { return _Parent; }
set { SetPropertyValue("Parent", ref _Parent, value); }
}
}
如您所见,保存1001(1000个孩子+ 1个父亲)需要7秒,而在下一个块中,更新1个父对象需要4秒。我已经针对MS Access和MS SQL 2008以及MSSQL-Compact进行了测试,但都具有相同的结果。任何建议都表示赞赏。
答案 0 :(得分:1)
对于1001个离散插入物来说,这似乎是合理的时间长度。对象保存在内存中,直到您调用CommitChanges,此时它们将被写入数据库。我没有描述XPO生成的SQL,但如果每个插入都发生在它自己的隐式事务中,我也不会感到惊讶。
修改强>
我已经使用Filip建议的跟踪编译了代码,第二个NestedUnitOfWork实际上正在更新所有子代,即使没有工作要做(这是在12.1.7版本中)。我不确定这是不是设计,但对我来说这似乎是一个错误。
为避免不必要地更新子项,您可以实例化一个普通的UnitOfWork:
using (var uow = new UnitOfWork())
{
//...
}
这只会更新父对象。但要小心:您仍然需要NestedUnitOfWork来进行会影响子对象的更新。