zoukankan      html  css  js  c++  java
  • 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集合内的[实体]同步.

    1. ApplyPropertyChanges调用时,要求对应的[实体]在内存中,Attach不要求
    2. pplyPropertyChanges调用后,集合内的实体状态会标记为EntityState.Modified
      Attach调用后不会修改合内的实体状态,如要SaveChanges(),要手动标记EntityState.Modified
    3. 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

    {

    }

    }

     

     

     

     

     

     

  • 相关阅读:
    python3调用js的库之execjs
    字体替换 re.sub
    asyncio和aiohttp
    微信公众号数据抓取
    celery
    Airtest 的连接安卓模拟器
    Scrapy同时启动多个爬虫
    随机IP代理插件Scrapy-Proxies
    Charles和mitmproxy代理设置
    win下删除EFI分区
  • 原文地址:https://www.cnblogs.com/foundation/p/1304706.html
Copyright © 2011-2022 走看看