MEMO-LINQ DataContext對Primary Key相同物件的處理原則
4 |
今天在寫程式時,發現LINQ to SQL在管理物件上的特殊規則,做個筆記。
假設我們有一個Member資料表如下:
有一段程式,其中很取巧的用Member去承接ExecuteQuery的執行結果,前後取得四顆物件,放入一個List
protected void Page_Load(object sender, EventArgs e)
{
using (PlaygroundDataContext db =
new PlaygroundDataContext())
{
List<Member> lst = new List<Member>();
var m = (from o in db.Members
where o.UserId == 1
select o).First();
lst.Add(m);
//借用Member類別,承接ExecuteQuery的結果
var n =
db.ExecuteQuery<Member>(@"
select 1 as UserId, 'Jeffrey' as UserName,
'ZZZ' as Code, getdate() as RegTime UNION
select 2 as UserId, 'Ninja' as UserName,
'XXX' as Code, getdate() as RegTime"
).ToArray();
lst.AddRange(n);
var r = (from o in db.Members
where o.UserId == 2
select o).First();
lst.Add(r);
//猜看看,結果是什麼?
foreach (var o in lst)
Response.Write(
string.Format("<li>{0}|{1}|{2}|{3:yyyy/MM/dd HH:mm}" ,
o.UserId, o.UserName, o.Code, o.RegTime));
}
Response.End();
}
大家猜看看,網頁會傳回什麼結果? X147, Jeffrey, Ninja, Darkthread? 錯!
- 1|X147|F1|2000/01/01 00:00
- 1|X147|F1|2000/01/01 00:00
- 2|Ninja|XXX|2010/08/13 18:58
- 2|Ninja|XXX|2010/08/13 18:58
由測試結果看來,在一個DataContext中,當Priimary Key相同的物件重複出現時,DataContext只會保留較早出現的那個版本。
若要避免上述物件依Primary Key自動合併及抛棄的狀況,我想到的解法是拆出不同的DataContext:
protected void Page_Load(object sender, EventArgs e)
{
List<Member> lst = new List<Member>();
using (PlaygroundDataContext db =
new PlaygroundDataContext())
{
var m = (from o in db.Members
where o.UserId == 1
select o).First();
lst.Add(m);
var r = (from o in db.Members
where o.UserId == 2
select o).First();
lst.Add(r);
}
using (PlaygroundDataContext db =
new PlaygroundDataContext())
{
//借用Member類別,承接ExecuteQuery的結果
var n =
db.ExecuteQuery<Member>(@"
select 1 as UserId, 'Jeffrey' as UserName,
'ZZZ' as Code, getdate() as RegTime UNION
select 2 as UserId, 'Ninja' as UserName,
'XXX' as Code, getdate() as RegTime"
).ToArray();
lst.AddRange(n);
}
//猜看看,結果是什麼?
foreach (var o in lst)
Response.Write(
string.Format("<li>{0}|{1}|{2}|{3:yyyy/MM/dd HH:mm}",
o.UserId, o.UserName, o.Code, o.RegTime));
Response.End();
}
將ExecuteQuery隔離在另一個PlaygroundDataContext後,結果便符合我們的需求囉!
- 1|X147|F1|2000/01/01 00:00
- 2|Darkthread|A4|2012/12/21 00:00
- 1|Jeffrey|ZZZ|2010/08/13 19:05
- 2|Ninja|XXX|2010/08/13 19:05
Comments
# by xuzicn
當Primary Key相同的物件重複出現時,DataContext只會保留較早出現的那個版本。 这个说法并不成立。我看到这个结论之后非常的惊奇,并且用你的办法试了一下,得到的结果就是预料之中的状况。不知道你的程式码是怎么写的呢?
# by Jeffrey
to xuzicn, 當真? 莫非是某個條件下才會出現此狀況? 事實上我是在實務專案上遇到離奇現象後,才回到這個簡單的LINQ to SQL的Member物件(PK = UserId, in ASP.NET 3.5)上做測試,也驗證了同樣結果(若連兩次巧合導致該文產生錯誤結論,也真算是不幸了 orz)。 不曉得可否提供更多您測試的細節(.NET 3.5 or 4.0?, EF or LINQ to SQL? 如果有程式碼示意的話更好),讓我看看是否忽略了什麼地方?
# by xuzicn
LinQ to SQL, 3.5, sql server 2005 事实上程式码已经被我扔掉了...今天重新试了一下结果正如你所写,很难琢磨清楚。 不过还是要谢谢你,至少目前知道DataContext确实不适合singleton模式
# by xuzicn
DataContext的缓存,其实很烦,只有小型的项目会考虑LinQ但是小型项目上用不上cache 普通的人当然会觉得DataContext和SqlConnection一样是一个非常expensive的,从而使用singleton或者pool,我做到一半之后才发现完全不是这么回事