ADO.NET Entity Framework(3)ObjectContext
目录
2.5 ApplyPropertyChanges 修改实体 2
2.7 CreateEntityKey 创建EntityKey 3
2.8 GetObjectByKey/TryGetObjectByKey 通过EntityKey得到实体 3
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.5 GetModifiedProperties 得到被修改的属性 6
3.3.6 SetModified,SetModifiedProperty 标记为修改 7
4.2 Context.SavingChanges 事件 9
4.3 Context.AcceptAllChanges 方法 9
5.1 Context.DefaultContainerName 属性 9
5.3 Context.CommandTimeout 属性 10
6 Context.MetadataWorkspace 10
7.3 ObjectContext.Refresh() 11
7.4 也可以先Refresh()再SaveChanges(),而不用异常捕获 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 { } } |