程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> ADO.NET Entity Framework(3)ObjectContext

ADO.NET Entity Framework(3)ObjectContext

編輯:關於.NET

目錄

1  說明  1

2  Context操作數據  1

2.1  AddObject 添加實體  1

2.2  DeleteObject 刪除實體  1

2.3  Detach 分離實體  2

2.4  修改實體  2

2.5  ApplyPropertyChanges 修改實體  2

2.6  Attach / AttachTo 附加實體  2

2.7  CreateEntityKey 創建EntityKey  3

2.7.1  EntityKey  3

2.8  GetObjectByKey/TryGetObjectByKey 通過EntityKey得到實體  3

2.9  CreateQuery 創建查詢  4

3  狀態管理  4

3.1  EntityState 狀態枚舉  4

3.2  Context.ObjectStateManager 管理記錄的狀態  4

3.2.1  GetObjectStateEntry 得到狀態實體  4

3.2.2  TryGetObjectStateEntry 得到狀態實體  4

3.2.3  GetObjectStateEntries 得到狀態實體集合  5

3.2.4  ObjectStateManagerChanged 事件  5

3.3  ObjectStateEntry 對象  5

3.3.1  基本屬性  5

3.3.2  State 狀態屬性  6

3.3.3  CurrentValues 當前值  6

3.3.4  OriginalValues 原始值  6

3.3.5  GetModifiedProperties 得到被修改的屬性  6

3.3.6  SetModified,SetModifiedProperty 標記為修改  7

3.3.7  Delete 標記為刪除  7

3.3.8  AcceptChanges 方法  7

4  保存修改到數據庫  8

4.1  Context.SaveChanges 方法  8

4.2  Context.SavingChanges 事件  9

4.3  Context.AcceptAllChanges 方法  9

5  連接屬性  9

5.1  Context.DefaultContainerName 屬性  9

5.2  Context.Connection 屬性  9

5.3  Context.CommandTimeout 屬性  10

6  Context.MetadataWorkspace  10

7  數據刷新與並發  10

7.1  緩存數據不會自動更新  10

7.2  [並發模式]值為[Fixed]的並發異常  11

7.3  ObjectContext.Refresh()  11

7.3.1  StoreWins  11

7.3.2  ClientWins  12

7.4  也可以先Refresh()再SaveChanges(),而不用異常捕獲  13

8  事務處理  13

8.1  同一SubmitChanges 會做默認的事務處理  13

8.2  不同SubmitChanges 不會做事務處理  13

8.3  System.Data.Common.DbTransaction  13

8.4  死鎖(兩個Context使用DbTransaction)  14

8.5  TransactionScope 事務(兩個Context)  14

說明

ObjectContext提供了管理數據的功能

Context操作數據 AddObject 添加實體

將實體添加到集合中,

創建實體時,狀態為EntityState.Detached

當調用AddObject將實體添加到Context時,狀態為EntityState.Added

myContext context = new myContext();

myTab r = new myTab();
r.ID = 10;
r.a = "wxwinter";

Console.WriteLine(r.EntityState); //print:Detached

context.AddTomyTab(r);

Console.WriteLine(r.EntityState); //print:Added

context.SaveChanges();
myContext context = new myContext();

myTab newrow = new myTab() { a = "wxd", b = "lzm", c = "wxwinter" };

context.AddObject("myTab",newrow);

context.SaveChanges();

DeleteObject 刪除實體

將集合中的實體添標記為刪除

當調用Context.DeleteObject時,並不是將實體移除集合,而是將實體添標記為EntityState.Deleted

myContext context = new myContext();

myTab r = context.myTab.First(p=>p.ID==1);

Console.WriteLine(r.EntityState); //print:Unchanged

context.DeleteObject(r);

Console.WriteLine(r.EntityState); //print:Deleted

context.SaveChanges();

Detach 分離實體

將實體從Context中移除,將狀態標記為EntityState.Detached

myContext context = new myContext();

myTab r = myTab.CreatemyTab(22);

Console.WriteLine(r.EntityState); //print:Detached

context.AddTomyTab(r);

Console.WriteLine(r.EntityState); //print:Added

context.Detach(r);

Console.WriteLine(r.EntityState); //print: Detached

修改實體

可以直接修在實體對象上修改

當修改在Context中的實體時,會將實體的狀態標記為EntityState.Modified

myContext context = new myContext();

myTab r = context.myTab.First(p=>p.ID==1);
Console.WriteLine(r.EntityState); //print:Unchanged
r.a = "wxwinter";
Console.WriteLine(r.EntityState); //print:Modified

context.SaveChanges();

ApplyPropertyChanges 修改實體

使用ApplyPropertyChanges,可以使用不在集合中的實體覆蓋到集合中主鍵對應用實體上

如果內存中沒有主鍵對應的記錄,會報錯

myContext context = new myContext();
myTab r1 = context.myTab.First(p => p.ID == 1);

myTab nr = myTab.CreatemyTab(1);
nr.a = "wxwinter";

Console.WriteLine(nr.EntityState); //print:Detached
Console.WriteLine(r1.EntityState); //print:Unchanged

context.ApplyPropertyChanges("myTab", nr);

myTab r2 = context.myTab.First(p => p.ID == 1);

Console.WriteLine(nr.EntityState); //print:Detached
Console.WriteLine(r2.EntityState); //print:Modified

context.SaveChanges();

Attach / AttachTo 附加實體

使用Attach方法可將[外部實體]附加到Context集合中

在使用 服務器/客戶端模式,或要將[實體]從Context集合中分離,修改後要用Context更新回數據庫時,可用這種方式

Attach與ApplyPropertyChanges有類似之處,都是將Context集合外的[實體]與Context集合內的[實體]同步.

ApplyPropertyChanges調用時,要求對應的[實體]在內存中,Attach不要求

pplyPropertyChanges調用後,集合內的實體狀態會標記為EntityState.Modified

Attach調用後不會修改合內的實體狀態,如要SaveChanges(),要手動標記EntityState.Modified

ApplyPropertyChanges是用[外部實體]全覆蓋Context集合中的[實體],

Attach方式,通過SetModifiedProperty()方法,可在調用SaveChanges()時,只修改只定有字段值

myContext context = new myContext();

myTab v = myTab.CreatemyTab(1);

v.EntityKey = context.CreateEntityKey("myTab", v);
v.a = "wxwinter";

context.Attach(v);
//context.AttachTo("myTab", v);

ObjectStateEntry ose = context.ObjectStateManager.GetObjectStateEntry(v);

ose.SetModified();

ose.SetModifiedProperty("a");

context.SaveChanges();

修改前

修改後

CreateEntityKey 創建EntityKey

myContext context = new myContext();

myTab nr = myTab.CreatemyTab(1);

EntityKey ek= context.CreateEntityKey("myTab", nr);

EntityKey

EntityContainerName 屬性   EntityKeyValues 集合   EntitySetName 屬性   IsTemporary 屬性   GetEntitySet(System.Data.Metadata.Edm.MetadataWorkspace) 方法   OnDeserialized(System.Runtime.Serialization.StreamingContext) 方法   OnDeserializing(System.Runtime.Serialization.StreamingContext) 方法  

GetObjectByKey/TryGetObjectByKey 通過EntityKey得到實體

myContext context = new myContext();

myTab nr = myTab.CreatemyTab(1);

EntityKey ek= context.CreateEntityKey("myTab", nr);

myTab r = context.GetObjectByKey(ek) as myTab ;

Console.WriteLine("{0},{1},{2},{3}", r.ID, r.a, r.b, r.c);
myContext context = new myContext();

myTab nr = myTab.CreatemyTab(1);

EntityKey ek= context.CreateEntityKey("myTab", nr);

object obj;
if (context.TryGetObjectByKey(ek,out obj))
{

myTab r = obj as myTab;
Console.WriteLine("{0},{1},{2},{3}", r.ID, r.a, r.b, r.c);
}

CreateQuery 創建查詢

更多見esql

myContext context = new myContext();

string esql = "SELECT VALUE DBItemList FROM myContext.DBItemList";

// ObjectQuery<DBItemList> query = new ObjectQuery<DBItemList>(esql, context);

ObjectQuery<DBItemList> query = context.CreateQuery<DBItemList>(esql);

foreach (DBItemList r in query)
{
Console.WriteLine(r.NameID);
}

狀態管理 EntityState 狀態枚舉

EntityState.Added 已通過AddObject方法加到集合中,AcceptChanges 尚未調用。

EntityState.Deleted 已通過 DeleteObject 方法被刪除。

EntityState.Detached 已被創建,但不屬於任何集合。在以下情況下立即處於此狀態:創建之後添加到集合中之前;或從集合中移除之後。

EntityState.Modified 已被修改,AcceptChanges 尚未調用。

EntityState.Unchanged 自上次調用 AcceptChanges 以來尚未更改

Context.ObjectStateManager 管理記錄的狀態 GetObjectStateEntry 得到狀態實體

ObjectStateEntry = GetObjectStateEntry(實體對像/EntityKey)

得到所指定的[實體對像]或EntityKey的 ObjectStateEntry

myContext context = new myContext();
myTab r = myTab.CreatemyTab(22);
context.AddTomyTab(r);

// ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);
ObjectStateEntry ose = context.ObjectStateManager.GetObjectStateEntry(r.EntityKey);

Console.WriteLine(ose.State); //print:Added

TryGetObjectStateEntry 得到狀態實體

bool = TryGetObjectStateEntry(實體對像/EntityKey,out ObjectStateEntry)

得到所指定的[實體對像]或EntityKey的 ObjectStateEntry

myContext context = new myContext();

myTab r = myTab.CreatemyTab(22);

context.AddTomyTab(r);

ObjectStateEntry ose;

if( context.ObjectStateManager.TryGetObjectStateEntry(r,out ose))
{
Console.WriteLine(ose.State); //print:Added
}

GetObjectStateEntries 得到狀態實體集合

IEnumerable<ObjectStateEntry> = GetObjectStateEntries(EntityState枚舉)

返回IEnumerable<ObjectStateEntry>,得到EntityState枚舉所指定的某種狀態的列表

myContext context = new myContext();

myTab r = myTab.CreatemyTab(22);

context.AddTomyTab(r);

IEnumerable<ObjectStateEntry> oseList = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added);

foreach (ObjectStateEntry v in oseList)
{
Console.WriteLine("{0},{1},{2}", v.State, v.CurrentValues["ID"], v.EntitySet.Name);

}
//print:Added,22,myTab

ObjectStateManagerChanged 事件

CollectionChangeEventHandler(object sender, CollectionChangeEventArgs e)
e.Action : 集合操作行為
System.ComponentModel.CollectionChangeAction.Add
System.ComponentModel.CollectionChangeAction.Refresh
System.ComponentModel.CollectionChangeAction.Remove

e.Element : 操作的實體對象
void ObjectStateManager_ObjectStateManagerChanged(object sender, CollectionChangeEventArgs e)
{

Console.WriteLine(e.Action);

myTab v = e.Element as myTab;

Console.WriteLine("{0}",v.ID);
}
//===================================
myContext context = new myContext();
context.ObjectStateManager.ObjectStateManagerChanged+=new CollectionChangeEventHandler(ObjectStateManager_ObjectStateManagerChanged);
myTab r = myTab.CreatemyTab(22);

context.AddTomyTab(r);
/*
*print:
Add
22
*/

ObjectStateEntry 對象 基本屬性

IsRelationship 屬性

Entity 屬性

EntityKey 屬性

EntitySet 屬性

State 狀態屬性

EntityState 枚舉

myContext context = new myContext();
myTab r = myTab.CreatemyTab(22);
context.AddTomyTab(r);

ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);

Console.WriteLine(ose.State); //print:Added

CurrentValues 當前值

處於 deleted 或 detached 狀態的對象沒有當前值。

myContext context = new myContext();
myTab r = new myTab() { ID = 22, a = "wxwinter" };
context.AddTomyTab(r);

ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);

Console.WriteLine("{0},{1}",ose.CurrentValues["ID"],ose.CurrentValues["a"]);

//print: 22,wxwinter

OriginalValues 原始值

處於 added 或 detached 狀態的對象沒有原始值

myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);

r.a = "wxwinter";
ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);

Console.WriteLine(ose.State);
Console.WriteLine("CurrentValues :{0},{1}", ose.CurrentValues["ID"], ose.CurrentValues["a"]);
Console.WriteLine("OriginalValues:{0},{1}", ose.OriginalValues["ID"], ose.OriginalValues["a"]);
/*
* print:
Modified
CurrentValues :1,wxwinter
OriginalValues:1,aa
*/

GetModifiedProperties 得到被修改的屬性

返回IEnumerable<string>

得到被修改的屬性集合

myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);

r.a = "wxwinter";
r.b = "wxd";

ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);
IEnumerable<string> list = ose.GetModifiedProperties();
foreach (string pr in list)
{
Console.WriteLine(pr);
}
/*
* print:
a
b
*/

SetModified,SetModifiedProperty 標記為修改

SetModified() 方法將記錄標記為 EntityState.Modified

只是這樣,調用Context.SaveChanges方法是無法保存修改到數據庫中的,Context.SaveChanges方法要查找被修改過的屬性,

可用SetModifiedProperty方法標記被修改過的屬性

myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);

r.a = "wxwinter";

ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);
ose.AcceptChanges();

Console.WriteLine(ose.State);
Console.WriteLine("CurrentValues :{0},{1}", ose.CurrentValues["ID"], ose.CurrentValues["a"]);
Console.WriteLine("OriginalValues:{0},{1}", ose.OriginalValues["ID"], ose.OriginalValues["a"]);
/*
* print:
Unchanged
CurrentValues :1,wxwinter
OriginalValues:1,wxwinter
*/

ose.SetModified();
ose.SetModifiedProperty("a");

Console.WriteLine(ose.State);
Console.WriteLine("CurrentValues :{0},{1}", ose.CurrentValues["ID"], ose.CurrentValues["a"]);
Console.WriteLine("OriginalValues:{0},{1}", ose.OriginalValues["ID"], ose.OriginalValues["a"]);

/*
* print:
Modified
CurrentValues :1,wxwinter
OriginalValues:1,wxwinter
*/
context.SaveChanges();

Delete 標記為刪除

標記為EntityState.Deleted

myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);
ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);
ose.Delete();
Console.WriteLine(ose.State); //print: Detached

Console.WriteLine("OriginalValues:{0},{1}", ose.OriginalValues["ID"], ose.OriginalValues["a"]);
//print:OriginalValues:1,wxwinter

用 context.DeleteObject方法的效果與上例一樣

myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);

ObjectStateEntry ose = context.ObjectStateManager.GetObjectStateEntry(r);

context.DeleteObject(r);

Console.WriteLine(ose.State); //print: Detached

Console.WriteLine("OriginalValues:{0},{1}", ose.OriginalValues["ID"], ose.OriginalValues["a"]);
//print:OriginalValues:1,wxwinter

AcceptChanges 方法

將記錄的狀態置為EntityState.Unchanged

用[CurrentValues 當前值]替換[OriginalValues 原始值],

使用[ Context.AcceptAllChanges 方法]也有同樣效果

注意:狀態為[EntityState.Deleted ]的記錄,會被[Detach]

myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);

r.a = "wxwinter";
context.AcceptAllChanges();

ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);
ose.AcceptChanges();
Console.WriteLine(ose.State);
Console.WriteLine("CurrentValues :{0},{1}", ose.CurrentValues["ID"], ose.CurrentValues["a"]);
Console.WriteLine("OriginalValues:{0},{1}", ose.OriginalValues["ID"], ose.OriginalValues["a"]);
/*
* print:
Unchanged
CurrentValues :1,wxwinter
OriginalValues:1,wxwinter
*/
當調用AcceptChanges時,如果對像處於[EntityState.Deleted ],會將對象移除集合,這時對像的狀態為[EntityState.Detached ]

myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);
ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);
ose.Delete();
ose.AcceptChanges();
Console.WriteLine(ose.State); //print: Detached

保存修改到數據庫 Context.SaveChanges 方法

如果集合中有狀態為EntityState.Added的記錄,用[CurrentValues 當前值]添加到數據庫中

如果集合中有狀態為EntityState.Deleted的記錄,從數據庫是刪除與之對應的數據庫記錄

如果集合中有狀態為EntityState.Modified的記錄,用[OriginalValues 原始值]與對應的數據庫記錄比效,查看並發, 用[CurrentValues 當前值]更新與之對應的數據庫記錄

SaveChanges(true) 將數據保存到數據庫後
將所有記錄狀態標記為EntityState.Unchanged ,(調用Context.AcceptAllChanges ) myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);

r.a = "wxwinter";
ObjectStateEntry ose = context.ObjectStateManager.GetObjectStateEntry(r);

context.SaveChanges(true);

Console.WriteLine(ose.State);
Console.WriteLine("CurrentValues :{0},{1}", ose.CurrentValues["ID"], ose.CurrentValues["a"]);
Console.WriteLine("OriginalValues:{0},{1}", ose.OriginalValues["ID"], ose.OriginalValues["a"]);

/*
* print:
Unchanged
CurrentValues :1,wxwinter
OriginalValues:1,wxwinter
*/ SaveChanges() 與SaveChanges(true)相同 SaveChanges(false) 將數據保存到數據庫,
但並不改變記錄狀態 myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);

r.a = "wxwinter";
ObjectStateEntry ose = context.ObjectStateManager.GetObjectStateEntry(r);

context.SaveChanges(false);

Console.WriteLine(ose.State);
Console.WriteLine("CurrentValues :{0},{1}", ose.CurrentValues["ID"], ose.CurrentValues["a"]);
Console.WriteLine("OriginalValues:{0},{1}", ose.OriginalValues["ID"], ose.OriginalValues["a"]);

/*
* print:
Modified
CurrentValues :1,wxwinter
OriginalValues:1,aa
*/

Context.SavingChanges 事件

myContext context = new myContext();
context.SavingChanges+=new EventHandler(context_SavingChanges);
myTab r = context.myTab.First(p => p.ID == 1);

r.a = "wxwinter";

context.SaveChanges();
void context_SavingChanges(object sender, EventArgs e)
{
myContext context = sender as myContext;
Console.WriteLine(context.DefaultContainerName);
}

Context.AcceptAllChanges 方法

將所有記錄的狀態置為EntityState.Unchanged

用[CurrentValues 當前值]替換[OriginalValues 原始值]

效果與對所在記錄的ObjectStateEntry上調用AcceptAllChanges一樣

注意:狀態為[EntityState.Deleted ]的記錄,會被[Detach]

myContext context = new myContext();
myTab r = context.myTab.First(p => p.ID == 1);

r.a = "wxwinter";
context.AcceptAllChanges();

ObjectStateEntry ose= context.ObjectStateManager.GetObjectStateEntry(r);
Console.WriteLine(ose.State);
Console.WriteLine("CurrentValues :{0},{1}", ose.CurrentValues["ID"], ose.CurrentValues["a"]);
Console.WriteLine("OriginalValues:{0},{1}", ose.OriginalValues["ID"], ose.OriginalValues["a"]);
/*
* print:
Unchanged
CurrentValues :1,wxwinter
OriginalValues:1,wxwinter
*/

連接屬性 Context.DefaultContainerName 屬性 Context.Connection 屬性 Context.CommandTimeout 屬性 Context.MetadataWorkspace 數據刷新與並發

EF提供了兩種並發沖突處理方式:放任不管方式和開放式並發。默認采用放任不管的方式處理。

如果要使用開放式並發,必須設置相應屬性上的[並發模式]值[Fixed]

後修改數據的ObjectContext緩存了舊版本的數據時,當提交修改後系統就會拋出"OptimisticConcurrencyException"(開放式並發異常)。

當程序捕獲到異常以後,可以使用ObjectContext的Refresh方法對異常采取處理。

緩存數據不會自動更新

公共 myContext context1 = new myContext();
myContext context2 = new myContext(); 查詢 foreach (var r in context1.DBItem)
{
Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter);
}

Console.WriteLine("---------------------");

foreach (var r in context2.DBItem)
{
Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter);
} a,this is a
b,this is b
c,this is c
---------------------
a,this is a
b,this is b
c,this is c 修改 DBItem dbitem1 = context1.DBItem.First(p => p.ItemID == "a");
dbitem1.ItemMatter = "hello";
context1.SaveChanges(); 再查詢 foreach (var r in context1.DBItem)
{
Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter);
}

Console.WriteLine("---------------------");

foreach (var r in context2.DBItem)
{
Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter);
} a,hello
b,this is b
c,this is c
---------------------
a,this is a
b,this is b
c,this is c

[並發模式]值為[Fixed]的並發異常

注意,只有後修改數據的ObjectContext緩存了舊版本的數據時,長會產生異常

DBItem dbitem1 = context1.DBItem.First(p => p.ItemID == "a");
dbitem1.ItemMatter = "hello";
context1.SaveChanges();

DBItem dbitem2 = context2.DBItem.First(p => p.ItemID == "a");
dbitem2.ItemMatter = "wxwinter";
context2.SaveChanges();

ObjectContext.Refresh()

Refresh的第一個參數RefreshMode枚舉,RefreshMode.StoreWins,RefreshMode.ClientWins

StoreWins

StoreWins : Refresh以後,用數據庫的值回寫,當前的修改值被放棄

公共 myContext context1 = new myContext();
myContext context2 = new myContext(); 查詢 foreach (var r in context1.DBItem)
{
Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter);
}

Console.WriteLine("---------------------");

foreach (var r in context2.DBItem)
{
Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter);
} a,this is a
b,this is b
c,this is c
---------------------
a,this is a
b,this is b
c,this is c 修改 DBItem dbitem1 = context1.DBItem.First(p => p.ItemID == "a");
dbitem1.ItemMatter = "hello";
context1.SaveChanges();

DBItem dbitem2 = context2.DBItem.First(p => p.ItemID == "a");

dbitem2.ItemMatter = "wxwinter";
try
{
context2.SaveChanges();
}
catch
{
context2.Refresh( RefreshMode.StoreWins , dbitem2);
} 在System.Data.OptimisticConcurrencyException 中第一次偶然出現的"System.Data.Entity.dll"類型的異常 再查詢 foreach (var r in context1.DBItem)
{
Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter);
}

Console.WriteLine("---------------------");

foreach (var r in context2.DBItem)
{
Console.WriteLine("{0},{1}", r.ItemID, r.ItemMatter);
} a,hello
b,this is b
c,this is c
---------------------
a,hello
b,this is b
c,this is c

ClientWins

StoreWins: Refresh以後,當前的修改值仍存在,只是告訴ObjectContext知到的並發問題了,這時再調用 ObjectContext.SaveChanges()時,ObjectContext就不會報[開放式並發異常]

DBItem dbitem1 = context1.DBItem.First(p => p.ItemID == "a");
dbitem1.ItemMatter = "hello";
context1.SaveChanges();

DBItem dbitem2 = context2.DBItem.First(p => p.ItemID == "a");

dbitem2.ItemMatter = "wxwinter";
try
{
context2.SaveChanges();
}
catch
{
context2.Refresh(RefreshMode.ClientWins, dbitem2);
context2.SaveChanges();
}

也可以先Refresh()再SaveChanges(),而不用異常捕獲

DBItem dbitem1 = context1.DBItem.First(p => p.ItemID == "a");
dbitem1.ItemMatter = "hello";
context1.SaveChanges();

DBItem dbitem2 = context2.DBItem.First(p => p.ItemID == "a");

dbitem2.ItemMatter = "wxwinter";

context2.Refresh(RefreshMode.ClientWins, dbitem2);
context2.SaveChanges();

事務處理 同一SubmitChanges 會做默認的事務處理

下例由於ItemID主鍵沖突,兩條數據都不會被插入

myContext context1 = new myContext();
DBItem item1 = new DBItem();
item1.ItemID = "w";
item1.ItemMatter = "wxwinter";
context1.AddObject("DBItem", item1);

DBItem item2 = new DBItem();
item2.ItemID = "w";
item2.ItemMatter = "wxd";
context1.AddObject("DBItem", item2);

context1.SaveChanges();

不同SubmitChanges 不會做事務處理

下例由於ItemID主鍵沖突,後一條數據都不會被插入

myContext context1 = new myContext();
DBItem item1 = new DBItem();
item1.ItemID = "w";
item1.ItemMatter = "wxwinter";
context1.AddObject("DBItem", item1);
context1.SaveChanges();

myContext context2 = new myContext();
DBItem item2 = new DBItem();
item2.ItemID = "w";
item2.ItemMatter = "wxd";
context2.AddObject("DBItem", item2);
context2.SaveChanges();

System.Data.Common.DbTransaction

下例由於ItemID主鍵沖突,兩條數據都不會被插入

myContext context1 = new myContext();
DBItem item1 = new DBItem();
item1.ItemID = "w";
item1.ItemMatter = "wxwinter";
context1.AddObject("DBItem", item1);

if (context1.Connection.State != ConnectionState.Open)
{
context1.Connection.Open();
}
System.Data.Common.DbTransaction tran = context1.Connection.BeginTransaction();
context1.SaveChanges();

try
{

DBItem item2 = new DBItem();
item2.ItemID = "w";
item2.ItemMatter = "wxd";
context1.AddObject("DBItem", item2);
context1.SaveChanges();
tran.Commit();
}
catch
{
tran.Rollback();
}

死鎖(兩個Context使用DbTransaction)

myContext context1 = new myContext();
DBItem item1 = new DBItem();
item1.ItemID = "w";
item1.ItemMatter = "wxwinter";
context1.AddObject("DBItem", item1);

if (context1.Connection.State != ConnectionState.Open)
{
context1.Connection.Open();
}
System.Data.Common.DbTransaction tran = context1.Connection.BeginTransaction();
context1.SaveChanges();

try
{
myContext context2 = new myContext();
DBItem item2 = new DBItem();
item2.ItemID = "w";
item2.ItemMatter = "wxd";
context2.AddObject("DBItem", item2);
context2.SaveChanges();
tran.Commit();
}
catch
{
tran.Rollback();
}

TransactionScope 事務(兩個Context)

System.Transactions.TransactionScope

可解決[死鎖(兩個Context使用DbTransaction)]

下例由於ItemID主鍵沖突,兩條數據都不會被插入

using (System.Transactions.TransactionScope tc = new TransactionScope())
{

try
{

myContext context1 = new myContext();
DBItem item1 = new DBItem();
item1.ItemID = "w";
item1.ItemMatter = "wxwinter";
context1.AddObject("DBItem", item1);
context1.SaveChanges();

myContext context2 = new myContext();
DBItem item2 = new DBItem();
item2.ItemID = "w";
item2.ItemMatter = "wxd";
context2.AddObject("DBItem", item2);
context2.SaveChanges();
tc.Complete();
}
catch
{
}
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved