西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁編程開發(fā) → XPO:Session管理與緩存--測試篇

XPO:Session管理與緩存--測試篇

相關(guān)軟件相關(guān)文章發(fā)表評論 來源:Elvin Chen時間:2010/2/12 10:14:57字體大小:A-A+

作者:不詳點擊:333次評論:0次標簽: Session

  • 類型:AVG冒險游戲大。817M語言:中文 評分:10.0
  • 標簽:
立即下載

之前整理了一下XPO在Session管理和緩存方面的一些資料(XPO:Session管理與緩存--機制篇),但原文的例程還是有些含糊的地方,這兩天抽空做了一下測試。若有不當或者不對的地方敬請不吝賜教。

 

XPO初始化的代碼就不重復貼了,這里只貼上主要的代碼。

測試中構(gòu)建了2個簡單的類,XpoUser和XpoOrder,一對多的關(guān)系。

XpoUser
using System;
using DevExpress.Xpo;

namespace Model
{
public class XpoUser : XPObject
{
public XpoUser()
: base()
{
// This constructor is used when an object is loaded from a persistent storage.
// Do not place any code here.
}

public XpoUser(Session session)
: base(session)
{
// This constructor is used when an object is loaded from a persistent storage.
// Do not place any code here.
}

public override void AfterConstruction()
{
base.AfterConstruction();
// Place here your initialization code.
}

private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
SetPropertyValue("Name", ref _Name, value);
}
}

[Association("XpoUser-Orders")]
public XPCollection<XpoOrder> Orders
{
get
{
return GetCollection<XpoOrder>("Orders");
}
}
}
}
 

 

 

XpoOrder
using System;
using DevExpress.Xpo;

namespace Model
{
public class XpoOrder : XPObject
{
public XpoOrder()
: base()
{
// This constructor is used when an object is loaded from a persistent storage.
// Do not place any code here.
}

public XpoOrder(Session session)
: base(session)
{
// This constructor is used when an object is loaded from a persistent storage.
// Do not place any code here.
}

public override void AfterConstruction()
{
base.AfterConstruction();
// Place here your initialization code.
}

private string _OrderID;
public string OrderID
{
get
{
return _OrderID;
}
set
{
SetPropertyValue("OrderID", ref _OrderID, value);
}
}

private XpoUser _User;
[Association("XpoUser-Orders")]
public XpoUser User
{
get
{
return _User;
}
set
{
SetPropertyValue("User", ref _User, value);
}
}
}
}
 

 

 

做了兩個測試,測試一的代碼:

Test1
ClearDB();
StringBuilder sb = new StringBuilder();
Session s1 = new Session();
Session s2 = new Session();
XpoUser user1 = new XpoUser(s1) { Name = "UserName" };
user1.Save();
XpoUser user2 = s2.FindObject<XpoUser>(new BinaryOperator("Name", "UserName"));
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));

sb.AppendLine(Environment.NewLine + "Change user's name in Session 1");
user1.Name = "New UserName";
user1.Save();
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));

sb.AppendLine(Environment.NewLine + "Create / Read something else(XpoRole) in Session 2");
XpoRole role = new XpoRole(s2) { Name = "RoleName" };
role.Save();
role = s2.FindObject<XpoRole>(new BinaryOperator("Name", "RoleName"));
sb.AppendLine(string.Format("Role name : {0}", role.Name));
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));

sb.AppendLine(Environment.NewLine + "Create / Read another XpoUser in Session 2");
XpoUser anotherUser = new XpoUser(s2) { Name = "Another User" };
anotherUser.Save();
anotherUser = s2.FindObject<XpoUser>(new BinaryOperator("Name", "Another User"));
sb.AppendLine(string.Format("Another user's name : {0}", anotherUser.Name));
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));

sb.AppendLine(Environment.NewLine + "Try to Save the user in Session 2, which is modified in Session 1");
try
{
user2.Save();
}
catch (Exception ex)
{
sb.AppendLine(ex.Message);
}
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));

sb.AppendLine(Environment.NewLine + "Session.Reload(User) in Session 2");
s2.Reload(user2);
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));

txtResult.Text = sb.ToString();
 

 

輸出的結(jié)果:

[Session 1] User's Name : UserName

[Session 2] User's Name : UserName

 


Change user's name in Session 1

[Session 1] User's Name : New UserName

[Session 2] User's Name : UserName

 


Create / Read something else(XpoRole) in Session 2

Role name : RoleName

[Session 1] User's Name : New UserName

[Session 2] User's Name : UserName

 


Create / Read another XpoUser in Session 2

Another user's name : Another User

[Session 1] User's Name : New UserName

[Session 2] User's Name : UserName

 


Try to Save the user in Session 2, which is modified in Session 1

Cannot persist the object. It was modified or deleted (purged) by another application.

[Session 1] User's Name : New UserName

[Session 2] User's Name : UserName

 


Session.Reload(User) in Session 2

[Session 1] User's Name : New UserName

[Session 2] User's Name : New UserName

 

可以看到:

2個不同Session里Load同一個object,確實是同一個object被傳遞給了2個Session,而并非該Object的任何副本。

在一個Session中對該Object做了修改后,其他Session除非Reload該對象,否則將永遠無法獲得其他Session對其做的改動。

同時,試圖保存這個已經(jīng)被其他Session所更改過的對象時會拋錯。

 

測試2:

Test2
ClearDB();
StringBuilder sb = new StringBuilder();
Session s1 = new Session();
Session s2 = new Session();
XpoUser user1 = new XpoUser(s1) { Name = "UserName" };
XpoOrder order = new XpoOrder(s1) { OrderID = "#1", User = user1 };
user1.Orders.Add(order);
user1.Save();
XpoUser user2 = s2.FindObject<XpoUser>(new BinaryOperator("Name", "UserName"));

sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 1] User's Order : {0}", GetOrders(user1)));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));
sb.AppendLine(string.Format("[Session 2] User's Order : {0}", GetOrders(user2)));


sb.AppendLine(Environment.NewLine + "Create a new order , change user's name and change Order1's ID to #3 in Session 1");
order = s1.FindObject<XpoOrder>(new BinaryOperator("OrderID", "#1"));
order.OrderID = "#3";
order.Save();
order = new XpoOrder(s1) { OrderID = "#2", User = user1 };
order.Save();
user1.Name = "New UserName";
user1.Orders.Add(order);
user1.Save();
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 1] User's Order : {0}", GetOrders(user1)));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));
sb.AppendLine(string.Format("[Session 2] User's Order : {0}", GetOrders(user2)));

sb.AppendLine(Environment.NewLine + "Session.Reload(User) in Session 2");
s2.Reload(user2);
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 1] User's Order : {0}", GetOrders(user1)));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));
sb.AppendLine(string.Format("[Session 2] User's Order : {0}", GetOrders(user2)));

sb.AppendLine(Environment.NewLine + "Session.Reload(User, forceAggregatesReload) in Session 2");
s2.Reload(user2, true);
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 1] User's Order : {0}", GetOrders(user1)));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));
sb.AppendLine(string.Format("[Session 2] User's Order : {0}", GetOrders(user2)));

sb.AppendLine(Environment.NewLine + "Load Order again in Session 2");
order = s2.FindObject<XpoOrder>(new BinaryOperator("OrderID", "#3"));
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 1] User's Order : {0}", GetOrders(user1)));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));
sb.AppendLine(string.Format("[Session 2] User's Order : {0}", GetOrders(user2)));

sb.AppendLine(Environment.NewLine + "Session.Reload(Order, forceAggregatesReload) in Session 2");
s2.Reload(order, true);
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 1] User's Order : {0}", GetOrders(user1)));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));
sb.AppendLine(string.Format("[Session 2] User's Order : {0}", GetOrders(user2)));

sb.AppendLine(Environment.NewLine + "Load Order2 in Session 2");
order = s2.FindObject<XpoOrder>(new BinaryOperator("OrderID", "#2"));
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 1] User's Order : {0}", GetOrders(user1)));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));
sb.AppendLine(string.Format("[Session 2] User's Order : {0}", GetOrders(user2)));

sb.AppendLine(Environment.NewLine + "Session.Reload(Order2, forceAggregatesReload) in Session 2");
s2.Reload(order, true);
sb.AppendLine(string.Format("[Session 1] User's Name : {0}", user1.Name));
sb.AppendLine(string.Format("[Session 1] User's Order : {0}", GetOrders(user1)));
sb.AppendLine(string.Format("[Session 2] User's Name : {0}", user2.Name));
sb.AppendLine(string.Format("[Session 2] User's Order : {0}", GetOrders(user2)));

txtResult.Text = sb.ToString();

 

 

上面代碼其實測試了幾種不同的情況,分別注釋掉后部幾個代碼塊單獨跑可以看得更清楚,這里只貼全部跑的結(jié)果:

[Session 1] User's Name : UserName

[Session 1] User's Order : #1

[Session 2] User's Name : UserName

[Session 2] User's Order : #1

 


Create a new order , change user's name and change Order1's ID to #3 in Session 1

[Session 1] User's Name : New UserName

[Session 1] User's Order : #3 #2

[Session 2] User's Name : UserName

[Session 2] User's Order : #1

 


Session.Reload(User) in Session 2

[Session 1] User's Name : New UserName

[Session 1] User's Order : #3 #2

[Session 2] User's Name : New UserName

[Session 2] User's Order : #1

 


Session.Reload(User, forceAggregatesReload) in Session 2

[Session 1] User's Name : New UserName

[Session 1] User's Order : #3 #2

[Session 2] User's Name : New UserName

[Session 2] User's Order : #1

 


Load Order again in Session 2

[Session 1] User's Name : New UserName

[Session 1] User's Order : #3 #2

[Session 2] User's Name : New UserName

[Session 2] User's Order : #3

 


Session.Reload(Order, forceAggregatesReload) in Session 2

[Session 1] User's Name : New UserName

[Session 1] User's Order : #3 #2

[Session 2] User's Name : New UserName

[Session 2] User's Order : #3

 


Load Order2 in Session 2

[Session 1] User's Name : New UserName

[Session 1] User's Order : #3 #2

[Session 2] User's Name : New UserName

[Session 2] User's Order : #3 #2

 


Session.Reload(Order2, forceAggregatesReload) in Session 2

[Session 1] User's Name : New UserName

[Session 1] User's Order : #3 #2

[Session 2] User's Name : New UserName

[Session 2] User's Order : #3 #2

 

 

在這個例子里,刷新User沒有獲得Order的變更,刷新Order也沒有獲得User的變更,更沒有獲得同一個User下其他Order的變更。

對于有一對多關(guān)系的結(jié)構(gòu)來說,無論是刷新哪個對象,用不用forceAggregatesReload,都只會刷新到自己,不會對關(guān)聯(lián)對象做出更新。

是bug還是對forceAggregatesReload的理解有誤?

 


 

另一個問題是,在Session下并沒有找到DropCache()方法,只有一個DropIdentityMap()方法,而調(diào)用這個方法以后,再Reload其他對象會拋錯(對象已被Dispose)。在DevExpress的官網(wǎng)上大概搜了一下,也沒找到什么說法。

 

 


從上面的測試結(jié)果來看,我很同意DevExpress建議的,對每一組互相關(guān)聯(lián)的少量數(shù)據(jù)都使用一個單獨的Session,“大方”的使用。在保持數(shù)據(jù)之間的邏輯關(guān)系不會被破壞的情況下,顆粒度越小越好。 單一Session里包含的數(shù)據(jù)越少,則這些數(shù)據(jù)的時間跨度就越小,而且一般說來也越快會被更新。如果想徹底拋棄一個Session的緩存重新加載的話,最好就直接new一個Session來做,而不要去Drop什么的了。

    相關(guān)評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字數(shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)
    推薦文章

    沒有數(shù)據(jù)

      沒有數(shù)據(jù)
    最新文章
      沒有數(shù)據(jù)