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

  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
{
}
}

本文作者:
« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3