从BLL中的一个方法跨多个DAL方法进行的事务
您将如何从业务逻辑层中的一个方法调用数据访问层中的多个方法,以便所有SQL命令都存在于一个SQL事务中?
可以从BLL中的其他位置单独调用每个DAL方法,因此无法保证数据层方法始终是事务的一部分。 我们需要这个function,所以如果数据库在长时间运行的过程中脱机,那么就没有提交。 业务层基于每个先前调用的结果来编排不同的数据层方法调用。 我们只想在整个过程的最后提交(从业务层)。
首先,您必须遵守您在BLL中指定为单个方法的primefaces工作单元。 这将(例如)创建客户,订单和订单商品。 然后,您可以将所有内容整齐地包装在TransactionScope using语句中。 TransactionScope是这里的秘密武器。 下面是一些代码,幸运的是我现在正在努力:):
public static int InsertArtist(Artist artist) { if (artist == null) throw new ArgumentNullException("artist"); int artistid = 0; using (TransactionScope scope = new TransactionScope()) { // insert the master Artist /* we plug the artistid variable into any child instance where ArtistID is required */ artistid = SiteProvider.Artist.InsertArtist(new ArtistDetails( 0, artist.BandName, artist.DateAdded)); // insert the child ArtistArtistGenre artist.ArtistArtistGenres.ForEach(item => { var artistartistgenre = new ArtistArtistGenreDetails( 0, artistid, item.ArtistGenreID); SiteProvider.Artist.InsertArtistArtistGenre(artistartistgenre); }); // insert the child ArtistLink artist.ArtistLinks.ForEach(item => { var artistlink = new ArtistLinkDetails( 0, artistid, item.LinkURL); SiteProvider.Artist.InsertArtistLink(artistlink); }); // insert the child ArtistProfile artist.ArtistProfiles.ForEach(item => { var artistprofile = new ArtistProfileDetails( 0, artistid, item.Profile); SiteProvider.Artist.InsertArtistProfile(artistprofile); }); // insert the child FestivalArtist artist.FestivalArtists.ForEach(item => { var festivalartist = new FestivalArtistDetails( 0, item.FestivalID, artistid, item.AvailableFromDate, item.AvailableToDate, item.DateAdded); SiteProvider.Festival.InsertFestivalArtist(festivalartist); }); BizObject.PurgeCacheItems(String.Format(ARTISTARTISTGENRE_ALL_KEY, String.Empty, String.Empty)); BizObject.PurgeCacheItems(String.Format(ARTISTLINK_ALL_KEY, String.Empty, String.Empty)); BizObject.PurgeCacheItems(String.Format(ARTISTPROFILE_ALL_KEY, String.Empty, String.Empty)); BizObject.PurgeCacheItems(String.Format(FESTIVALARTIST_ALL_KEY, String.Empty, String.Empty)); BizObject.PurgeCacheItems(String.Format(ARTIST_ALL_KEY, String.Empty, String.Empty)); // commit the entire transaction - all or nothing scope.Complete(); } return artistid; }
希望你能得到主旨。 基本上,它是一个成功或失败的工作,无论任何不同的数据库(即在上面的例子中,艺术家和artistartistgenre可以托管在两个单独的数据库存储中,但TransactionScope不关心它,它在COM +级别工作并管理primefaces性它可以“看到”的范围
希望这可以帮助
编辑:您可能会发现TransactionScope的初始调用(在应用程序启动时)可能会略微明显(例如,在上面的示例中,如果是第一次调用,可能需要2-3秒才能完成),但是,后续呼叫几乎是瞬时的(即通常为250-750毫秒)。 简单的联系交易与(笨重的)替代方案之间的权衡减轻了(对我和我的客户而言)最初的“加载”延迟。
只是想表明轻松不会妥协(尽管在初始阶段)
你所描述的是长期交易的“定义”。
每个DAL方法都可以简单地提供操作(没有任何特定的提交)。 您的BLL(无论如何协调对DAL的任何调用都是有效的)是您可以选择提交或执行“保存点”的地方。 保存点是一个可选项,您可以使用它来允许在长时间运行的事务中进行“回滚”。
因此,例如,如果我的DAL具有方法DAL1,DAL2,DAL3都是可变的,则它们将简单地“执行”数据更改操作(即某种类型的创建,更新,删除)。 从我的BLL,假设我有BL1和BL2方法(BL1长时间运行)。 BL1调用所有上述DAL方法(即DAL1 … DAL3),而BL2仅调用DAL3。
因此,在执行每个业务逻辑方法时,您可能具有以下内容:
BL1(长事务) – > {savepoint} DAL1 – > {savepoint} DAL2 – > DAL3 {commit / end}
BL2 – > DAL3 {commit / end}
“保存点”背后的想法是,如果数据操作存在问题,它可以允许BL1在任何时候回滚。 如果所有三个操作都成功完成,则仅提交长事务。 BL2仍然可以调用DAL中的任何方法,它负责控制提交。 注意:您也可以在短期/常规交易中使用“保存点”。
好问题。 这成为阻抗不匹配的核心。
这是使用存储过程的最强大的参数之一。 原因:它们旨在将多个SQL语句封装在事务中。
在DAL中可以在程序上完成相同的操作,但是它会导致代码的清晰度降低,同时通常会导致耦合/内聚平衡向错误的方向移动。
出于这个原因,我在更高的抽象级别实现DAL而不是简单地封装表。
为了防止我在原始文章中的评论没有“坚持”,这里是我添加的附加信息:
<-----巧合的是,刚刚注意到你的请求后几个小时发布了另一个类似的引用。 使用类似的策略,也许值得你看看:http://stackoverflow.com/questions/494550/how-does-transactionscope-roll-back-transactions ----->
- Application.Restart()是否为应用程序创建新进程或没有?
- 此客户端的邮件提交率是否超过配置的限制?
- 我可以从后台线程更新UI,为什么?
- 关闭.NET SerialPort后的ObjectDisposedExecption
- 如何从nuget包中排除子目录和内容
- 我可以在Visual Studio中创建一个位于.Designer.cs文件旁边的文件吗?
- 检查类型TA是否可以在运行时强制转换为TB? (考虑的不仅仅是inheritance)
- 从silverlight调用Java Web服务会引发exception
- 为什么这个Linq代码总是抛出System.StackOverflowException?