DataContext的讨论 2

我在成都,所以这两天因为地震所以影响一些正常的生活次序.

索引页

DataContext的讨论




一:Identity Tracking


LINQ to SQL 被设计用来解决对象与关系的的不协调,问题在于数据库是关系型的,而语言却是面向对象.我们解决这个问题就是加一个标识,如果我们在多个地方查询数据库,我们期望返回数据存在内存不同的位置.而当我们修改在内存中的记录集的域而不会影响相应的其他域.能这样做就因为数据存储在不同变量中,而变量有不同的地址.

DataContext类给我们提供Identity Tracking.(1)首先在DataContext实例化时记录集就被从数据库中查询出来,(2)使用他的主键记录这个记录集在一个标识表中,实体对象被创建和存储在cache中,接着就是检测标识表是否有相同记录出现.如果已经存在就返回实体对象.


二:Change Tracking


Change Tracking:它是按照存储的一个实体对象的最初值来工作.Change Tracking是一直跟踪到SubmitChanges方法.这时最初值被放弃,并被更改.但在你创建一个个新的实体对象实例,它将不会给跟踪和表识.

http://msdn.microsoft.com/zh-cn/library/bb386982.aspx


三:Change 过程


当你调用SubmitChanges方法时,这个DataContext 对象的change processor管理数据库的更新.首先change processor将插入所有新插入的实体对象到它的 tracked entity objcets list(被跟踪对象列表),接着它将按照外键和唯一性约束的下来更改实体对象.之后,如果没有事务,它将创建一个包含所有SQL命令的事务,提供给SubmitChanges调用.使用SQL Server默认的ReadCommitted的独立级别,提交数据即被读取,锁是共享锁,没有防止数据在事务提交前被更改.最后,枚举出相关的实体数据,生成所需的SQL语句,并执行.如果在枚举出相关的实体数据是有任何错误被触发,SubmitChanges方法就会使用FailOnFirstConfilct.ConflictMode,将这个枚举进程关闭,并且回滚事务,不再更改数据库,如果你将ContinueOnConflict的ConflictMode设置,所有被更改的实体对象将不关任何冲突的被触发继续枚举和处理.同时DataContext会构件一个conflict的列表,但还是要回滚事务,不更改数据库,只不过在这里是更改的实体仍然在,这样就能找出问题再次提交.


四:GetChangeSet方法;


提供对修改对象的跟踪.它返回的是一个只读的IList集合,如果你将你的db.ObjectTrackingEnabled = true;DataContext就会开始跟踪被更改对象,其实在只需要显示数据不需要更改实体,那就不需要使用这 个属性,这样可以提高性能.


五:Submit Changes to the Database



不管多少次更改你的工程,改变的只是替换你的内存中的数据.你没有更改到在数据库中真实的数据.你的改变没有传输到你的服务端,除非你明确调用SubmitChanges方法.

当你明确调用时,DataContext会试着去翻译你的更改,成相同的SQL 命令.你能使用自己定义的逻辑重写这些行为,但需要按照被命名为一个change processor的DataContext的服务的编制次序来做.次序是下面:

(1)当你调用SubmitChanges,LINQ to SQL检验一些列已知对象来决定是否为现有对象追加新实例.如果需要,这些新实例就会被添加到跟踪对象中.
(2)未决定改变的所有对象被放进有依赖关系的有序对象集中被排序.这些对象按照与其他对象的依赖关系来改变.
(3)任何被变化被立即传输前,LINQ to SQL开始一个事务去封装一系列的单独命令.
(4)提交改变的对象的行为被翻译成一句一句的SQL命令并发送到服务端.

要指出,数据库发现任何错误都会引起强制停止进程,并且一个异常会被抛出.如果没有强制停止没有被出发,那数据库的所有改变将会被回滚.在这里DataContext仍然改变完整的记录.因此你能在修改问题后再调用SubmitChanges.
下面是基本的使用


None.gif Northwnd db  =   new  Northwnd( @" c:\northwnd.mdf " );
None.gif
//  Make changes here. 
None.gif
try
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    db.SubmitChanges();
ExpandedBlockEnd.gif}

None.gif
catch  (ChangeConflictException e)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    Console.WriteLine(e.Message);
InBlock.gif    
// Make some adjustments.
InBlock.gif    
// dot.gif
InBlock.gif    
// Try again.
InBlock.gif
    db.SubmitChanges();
ExpandedBlockEnd.gif}

None.gif



二:几种得到全局唯一DataContext实例的方法:



首先要提到是Rick Strahl的blog,上面有很关于LINQ to SQL的探讨.它有一个案例,可以在这个地址下载, http://www.west-wind.com/files/conferences/conn_LinqToSqlBusiness.zip ,它对现有LINQ to SQL做一写封装(我感觉是没有多大意义),但整个代码比较完整,是很好的学习资料.

在它的blogs上有一个DataContextFactory类,在Web应用程序中使用WebRequest,在Winfrom应用程序中使用Thread,和通常的直接返回DataContext.
DataContextFactory类算是一种制造全局的DataContext的方法.

第二中就是使用HttpContext.Current
在你的DataContext的部分类中添加一个静态方法
None.gif public   static  ADWorksDataContext DataContextInstance
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (HttpContext.Current.Items["ADWorksDataContext"== null)
InBlock.gif                    HttpContext.Current.Items[
"ADWorksDataContext"= new ADWorksDataContext();
InBlock.gif
InBlock.gif                
return HttpContext.Current.Items["ADWorksDataContext"as ADWorksDataContext;
InBlock.gif
ExpandedSubBlockEnd.gif            }

ExpandedBlockEnd.gif        }


这样你就能利用之前在HttpContext中的创建的DataContext的实现,来创建新的实例.

第三中就是可以放在Global.asax文件中关键一个程序级的变量,来存放DataContext的实现,并来创建实例.

None.gif ADWorksDataContext db  =   new  ADWorksDataContext();
None.gif
None.gif            Application.Lock();
None.gif            Application[
" AllDataContext " =  db;
None.gif            Application.UnLock();

这样也是全局的.

也可以利用HttpApplication类来在整个应用程序周期中创建DataContext.

None.gif public   class  DataContextModule : IHttpModule
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
public void Dispose(HttpApplication context)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//dc.SubmitChanges();
InBlock.gif
            dc.Dispose();
InBlock.gif            dc 
= null;
InBlock.gif            context.Context.Items.Remove(
"$context");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void Init(HttpApplication context)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            context.PreRequestHandlerExecute 
+= new EventHandler(context_PreRequestHandlerExecute);
InBlock.gif            context.PostRequestHandlerExecute 
+= new EventHandler(context_PostRequestHandlerExecute);
InBlock.gif            
//context.PostReleaseRequestState+=new EventHandler(context_PostReleaseRequestState);
ExpandedSubBlockEnd.gif
        }

InBlock.gif
InBlock.gif
InBlock.gif        
//void context_PostReleaseRequestState(object sender, EventArgs e)
InBlock.gif        
//{
InBlock.gif
InBlock.gif        
//}
InBlock.gif
        void context_PreRequestHandlerExecute(object sender, EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            HttpApplication app 
= sender as HttpApplication;
InBlock.gif            
if (app.Context.Handler is Page)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ADWorksDataContext dc 
= new ADWorksDataContext();
InBlock.gif                app.Context.Items[
"$context"= dc;
InBlock.gif
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
void context_PostRequestHandlerExecute(object sender, EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            HttpApplication app 
= sender as HttpApplication;
InBlock.gif            
if (app.Context.Handler is Page)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ADWorksDataContext dc 
= app.Context.Items["$context"as ADWorksDataContext;
InBlock.gif
InBlock.gif
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }


其实有很多方法,主要是看需要,而自己写.
这里有很多讨论. http://www.west-wind.com/WebLog/posts/246222.aspx

索引页



worksguo
www.cnblogs.com/worksguo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值