EntityFramework MergeOption运用

最近尝试在sharepoint里面使用EF访问本地的数据库,由于sharepoint只能引用.net3.5的程序集,所以就只能使用EF1.1版本了,(吐槽一下:这个版本的EF由于是最早版本,所以不支持调用 存储过程:-(),下面说下具体遇到的问题吧。


首先了解下MergeOption

是ObjectContext管理查询返回的实体四种方式,他们分别是:

1.AppendOnly——如果要获取的实体在上下文里面,就直接从上下文里面取到,如果不在的话就把取出来的实体附加到上下文里面,这个是默认的方式,这种方式的好处就是会首先从内存里面找你要的实体,比较快。

2.NoTracking——上下文不存实体,这种方式就是说每次都从数据库里面取数据。

3.OverwriteChanges——如果要获取的实体在上下文中,那么该实体的值会被数据库的值覆盖,然后再返回,如果不在的话就把取出来的实体附加到上下文里面。

4.PreserveChanges——如果要获取的实体在上下文中,那么该实体中被用户修改的属性保持不变,其余的属性用数据库的值覆盖,如果不在的话话就把取出来的实体附加到上下文里面。


我遇到的问题

在上下文中构造了一个实体,将该实体标记为添加,该实体的一个流水号字段FlowCode是由数据库触发器自动生成的

BasicInfo binfo = new BaicInfo();
//主键
; Guid tempGuid=binfo.UIID = GUID.NewGuid();
binfo.Discription= "Test"; binfo.Type=1; ctx.BasicInfoEntities.Add(binfo);

然后ctx.SaveChanges();数据库触发器会给该记录自动生成FlowCode字段,于是就理所当然的想在该上下文中根据主键获取该记录的FlowCode,

string flowCode=ctx.BasicInfoEntities.Where(x=>x.UIID==tempGuid).FirstOrDefault().FlowCode;

但是奇怪的是取不到这个FlowCode,可是数据库里面明明这个字段的被触发器生成了,是有值的啊,郁闷,:-(,google了一番有所发现,原来在同一上下文中,调用SaveChanges()的时候EF会生成一大堆的SQL到数据库,数据库就会咔咔的执行,但是触发器是是在数据库里面执行的,所以数据库并不会通知EF说,你让我帮你插入一条数据的时候FlowCode字段的值是我用触发器生成的,这个值是多少多少,然后EF会更新到ObjectStateManger这个Entity对应的Entry里面。此时上下文里面的binfo实体的数据即使不是最新的(相对于数据库)它状态是UnChanged,又由于默认的MergeOption是AppendOnly,所以我们再去根据主键获取实体的时候会返回上下文中的实体,这样一来就当然取不到FlowCode的值了。


解决办法:重写MergeOption为NoTracking

方法一:永久设置实体集MergeOption为NoTracking

ctx.BasicInfoEntities.MergeOption = MergeOption.NoTracking;

方法二:只设置该次调用为NoTracking

string flowCode=ctx.BasicInfoEntities.Execute(MergeOption.NoTracking).Where(x=>x.UIID==tempGuid).FirstOrDefault().FlowCode;

这样就可以告诉EF从数据库取该实体的数据了,触发器生成的FLowCode就取出来鸟。  

posted @ 2012-12-10 23:03  firtuss  阅读(2489)  评论(4编辑  收藏  举报