集成 linq to sql 和spring.net

本文介绍如何将LINQ to SQL与Spring.NET集成,实现灵活的事务管理。通过自定义DataContextFactory和DataContextTemplate等组件,使得LINQ to SQL能够与Spring.NET的事务支持无缝结合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近一段时间,精力都放在将linq to sql 引入项目中的工作,由于框架所采用的ioc是spring.net , 将linq to sql 和spring.net集成也是自然的事情.可以预测的是,将来spring.net 官方必然会做这个事情. 所以,我目前的计划也只是满足自身所需的功能即可. 同时,此文也只是提供一种方法,细节请大家多多斟酌.

对于linq to sql 而言,同spring.net 集成的最大好处是事务机制, 你可以获得spring.net 灵活多变的事务支持,并提供你的非linq to sql 数据访问和linq to sql 运行在同一事务下的可能. 由于DataContext 由于你使用IDbConnection作为创建DataContext的参数,因此,不需要写很多代码就能和spring.data 的ado.net  事务支持集成.

集成主要包括以下部分
1. IDataContextFactory和其缺省实现DataContextFactory
2. LocalDataContextFactoryObject  ,其实如果原有的工厂类能符合ioc配置的需要,就没有必要为之提供对象的FactoryObject, 因为FactoryObject 通常需要重复一些配置属性,FactoryObject通常用于无法使用ioc配置的工厂类,通常,它也提供额外的配置检查功能. 我这个实现代码quick and dirty 建议大家不要学:)
3. DataContextTemplate

btw: 本来我不打算实现单独的DataContextFactory,但后来发现,为了符合spring.net 惯用法,这还是有必要的,现在的代码同上午略有不同

例子
None.gifTransactionTemplate tt = (TransactionTemplate)context.GetObject("transactionTemplate");
None.gif
ExpandedBlockStart.gifContractedBlock.gif      tt.Execute(
delegate(ITransactionStatus status)dot.gif{
InBlock.gif        template.Execute(
delegate(DataContext db)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif         
InBlock.gif          Currency c 
= new Currency();
InBlock.gif          c.Id 
= "t";
InBlock.gif          c.Name 
= "t";
InBlock.gif          c.ExchangeRate 
= 1;
InBlock.gif
InBlock.gif          db.GetTable
<Currency>().Add(c);
InBlock.gif
InBlock.gif          db.SubmitChanges();
InBlock.gif
InBlock.gif          
return null;
ExpandedSubBlockEnd.gif        }
);
InBlock.gif   
InBlock.gif
InBlock.gif        template.Execute(
delegate(DataContext db)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif          Currency c 
= db.GetTable<Currency>().FirstOrDefault(item => item.Id == "t");
InBlock.gif
InBlock.gif          db.GetTable
<Currency>().Remove(c);
InBlock.gif
InBlock.gif          db.SubmitChanges();
InBlock.gif
InBlock.gif          
return null;
ExpandedSubBlockEnd.gif        }
);
InBlock.gif
InBlock.gif        
return null;
ExpandedBlockEnd.gif      }
);

可以在插入后加一行 throw new Exception(); 来看看数据是否已经插入到数据库来检查工作是否正常.

声明
None.gif   <objects default-lazy-init="true" xmlns="http://www.springframework.net" xmlns:database="http://www.springframework.net/database">
None.gif      
<database:provider id="dbProvider" provider="SqlServer-2.0" connectionString="server=(local);user id=sa;pwd=;database=xxx"/>
None.gif      
<object id="dataContextFactory" type="SohoWorks.BusinessFramework.Data.Linq.LocalDataContextFactoryObject,SohoWorks.BusinessFramework">
None.gif        
<property name="DbProvider" ref="dbProvider"/>
None.gif        
<property name="DataContextType" value="xxxx,xxx"/>
None.gif      
</object>
None.gif      
<object id="dataContextTemplate" type="SohoWorks.BusinessFramework.Data.Linq.DataContextTemplate,SohoWorks.BusinessFramework">
None.gif        
<property name="DataContextFactory" ref ="dataContextFactory"></property>
None.gif      
</object>
None.gif
None.gif      
<object id="transactionManager" type="Spring.Data.Core.AdoPlatformTransactionManager,Spring.Data">
None.gif        
<property name="DbProvider" ref="dbProvider"/>
None.gif      
</object>
None.gif      
<object id="transactionTemplate" type="Spring.Transaction.Support.TransactionTemplate,Spring.Data">
None.gif        
<property name="PlatformTransactionManager" ref="transactionManager"/>
None.gif      
</object>
None.gif    
</objects>

DataContextFactory 是IDataContextFactory的默认实现, 它主要功能就是从一个DataContextType声明实例化DataContext,它只关心使用IDbConnection参数的那两个构造函数, DataContextFactory还可以提供额外的属性声明,像这个例子中的DefaultObjectTrackingEnabled之类的,以便你在实例化时进行相应的初始化.

最最关键的代码可能就是ConnectionUtils.GetConnectionTxPair了
IDataContextFactory
None.gif public interface IDataContextFactory
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{
InBlock.gif    DataContext GetDataContext();
InBlock.gif    
ExpandedBlockEnd.gif  }
DataContextFactory
None.gif public class DataContextFactory : IDataContextFactory
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{
InBlock.gif    
InBlock.gif    
private  ConstructorInfo constructorInfo;
InBlock.gif    
private  ConstructorInfo mappingSourceConstructorInfp;
InBlock.gif    
private Type _dataContextType;
InBlock.gif    
private IDbProvider dbProvider;
InBlock.gif
InBlock.gif    
public DataContextFactory(IDbProvider dbProvider, Type dataContextType)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
this.dbProvider = dbProvider;
ExpandedSubBlockStart.gifContractedSubBlock.gif      constructorInfo 
= dataContextType.GetConstructor(new Type[] dot.giftypeof(IDbConnection) });
ExpandedSubBlockStart.gifContractedSubBlock.gif      mappingSourceConstructorInfp 
= dataContextType.GetConstructor(new Type[] dot.giftypeof(IDbConnection), typeof(MappingSource) });
InBlock.gif      _dataContextType 
= dataContextType;
ExpandedSubBlockEnd.gif    }

InBlock.gif 
InBlock.gif    
public MappingSource MappingSource
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
get;
InBlock.gif      
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public IDbProvider DbProvider
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif      
get dot.gifreturn dbProvider; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
set dot.gif{ dbProvider = value; }
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public bool DefaultDeferredLoadingEnabled
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
get;
InBlock.gif      
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public bool DefaultObjectTrackingEnabled
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
get;
InBlock.gif      
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif
InBlock.gif    
public DataContext GetDataContext()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      DataContext dc 
= null;
InBlock.gif      ConnectionTxPair pair 
= ConnectionUtils.GetConnectionTxPair(DbProvider);
InBlock.gif      
if (MappingSource != null )
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif          dc 
= (DataContext)constructorInfo.Invoke(new object[] dot.gif{ pair.Connection, MappingSource });
ExpandedSubBlockEnd.gif      }

InBlock.gif      
else
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        dc 
= (DataContext)constructorInfo.Invoke(new object[] dot.gif{ pair.Connection });
ExpandedSubBlockEnd.gif      }

InBlock.gif      dc.DeferredLoadingEnabled 
= DefaultObjectTrackingEnabled;
InBlock.gif      dc.ObjectTrackingEnabled 
= DefaultObjectTrackingEnabled;
InBlock.gif      dc.Transaction 
= (DbTransaction)pair.Transaction;
InBlock.gif      
return dc;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
ExpandedBlockEnd.gif  }
LocalDataContextFactoryObject 主要用于配置, 它现在提供DataContextFactory的singleton实例,如上面所说,有时它不是必须的,它也会重复一些配置代码
ContractedBlock.gifExpandedBlockStart.gif
None.gif public class LocalDataContextFactoryObject : AbstractFactoryObject
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{
InBlock.gif    
InBlock.gif    
public LocalDataContextFactoryObject()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif    
InBlock.gif      DefaultDeferredLoadingEnabled 
= true;
InBlock.gif      DefaultObjectTrackingEnabled 
= true;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
private Type _dataContextType;
InBlock.gif 
InBlock.gif    
private IDbProvider dbProvider;
InBlock.gif    
public IResource MappingSource
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
get;
InBlock.gif      
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public IDbProvider DbProvider
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif      
get dot.gifreturn dbProvider; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
set dot.gif{ dbProvider = value; }
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public bool DefaultDeferredLoadingEnabled
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
get;
InBlock.gif      
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public bool DefaultObjectTrackingEnabled
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
get;
InBlock.gif      
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif
InBlock.gif    
protected override object CreateInstance()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif
InBlock.gif      DataContextFactory factory 
= new DataContextFactory(DbProvider, DataContextType);
InBlock.gif
InBlock.gif      
InBlock.gif      
if (MappingSource != null  && MappingSource.Exists)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        
using (Stream stream = MappingSource.InputStream)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif          factory.MappingSource 
= XmlMappingSource.FromStream(stream);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif      }

InBlock.gif      
InBlock.gif     factory.DefaultDeferredLoadingEnabled 
= DefaultObjectTrackingEnabled;
InBlock.gif     factory.DefaultObjectTrackingEnabled 
= DefaultObjectTrackingEnabled;
InBlock.gif
InBlock.gif     
return factory;
InBlock.gif
InBlock.gif      
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public override void AfterPropertiesSet()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
base.AfterPropertiesSet();
InBlock.gif      
if (DataContextType == null)
InBlock.gif        
throw new ArgumentNullException("DataContextType");
InBlock.gif      
if (DbProvider == null)
InBlock.gif        
throw new ArgumentNullException("DbProvider");
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
public Type DataContextType
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif      
get dot.gifreturn _dataContextType; }
InBlock.gif      
set
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        
if (!typeof(DataContext).IsAssignableFrom(value))
InBlock.gif          
throw new ArgumentException("DataContextType");
InBlock.gif        _dataContextType 
= value;
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
public override Type ObjectType
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif      
get dot.gifreturn typeof(IDataContextFactory); }
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif  }



DataContextTemplate 是一个重要的类, 它依赖IDataContextFactory, 并常用的数据方法, 如FindById,FindListById,Delete,Save,Update,之类的这里只摘录主要部分
None.gifpublic delegate object DoInDataContext(DataContext db);
None.gif
None.gif  
public class DataContextTemplate
ExpandedBlockStart.gifContractedBlock.gif  
dot.gif{
InBlock.gif    
private IDataContextFactory dataContextFactory;
InBlock.gif    
public IDataContextFactory DataContextFactory
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif      
get dot.gifreturn dataContextFactory; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
set dot.gif{ dataContextFactory = value; }
ExpandedSubBlockEnd.gif    }

InBlock.gif   
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public  void Execute(DoInDataContext doInDataContext)dot.gif{
InBlock.gif      
using (DataContext db = dataContextFactory.GetDataContext())
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif
InBlock.gif        doInDataContext(db);
ExpandedSubBlockEnd.gif      }

InBlock.gif   
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public  object Find(DoInDataContext doInDataContext)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
using (DataContext db = dataContextFactory.GetDataContext())
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif
InBlock.gif        
return doInDataContext(db);
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif    }

InBlock.gifdot.gifdot.gifdot.gifdot.gifdot.gif.
ExpandedBlockEnd.gif}



btw:

1. 我使用spring.net cvs上的代码,目前,如果要像我这样声明DbProvider ,则需要在应用程序启动前 加如下一行

None.gif  NamespaceParserRegistry.RegisterParser(typeof(DatabaseNamespaceParser));

2. IFactoryObject接口是spring的魔术接口之一, 当你从spring ioc获取一个实现该接口的对象时,它返回的并不是对象本身,而是IFactoryObject.GetObject方法返回的具体对象. 如果你要获取对象本身,则需要在对象id前加&

转载于:https://www.cnblogs.com/jjx/archive/2007/08/08/847749.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值