日期:2014-05-20  浏览次数:21077 次

ADO.NET Entity Framework学习笔记(3)ObjectContext对象

说明

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]

后修改