ADO.NET Entity Framework(3)ObjectContext

目录

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提供了管理数据的功能

ADO.NET Entity Framework(3)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();

修改前

ADO.NET Entity Framework(3)ObjectContext

修改后

ADO.NET Entity Framework(3)ObjectContext

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方法对异常采取处理。

ADO.NET Entity Framework(3)ObjectContext

ADO.NET Entity Framework(3)ObjectContext

缓存数据不会自动更新

公共

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();

ADO.NET Entity Framework(3)ObjectContext

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();
}

ADO.NET Entity Framework(3)ObjectContext

也可以先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
{
}
}

posted on 2010-04-26 10:48  l1b2q31  阅读(941)  评论(0编辑  收藏  举报

导航