从BLL中的一个方法跨多个DAL方法进行的事务

时间:2009-01-29 22:01:21

标签: c# .net sql

您如何从业务逻辑层中的一个方法调用数据访问层中的多个方法,以便所有SQL命令都存在于一个SQL事务中?

每个DAL方法都可以从BLL中的其他位置单独调用,因此无法保证数据层方法始终是事务的一部分。我们需要这个功能,所以如果数据库在长时间运行的进程中脱机,就没有提交。业务层基于每个先前调用的结果来编排不同的数据层方法调用。我们只想在整个过程的最后提交(从业务层)。

4 个答案:

答案 0 :(得分:8)

嗯,首先,您必须遵守您在BLL中指定为单个方法的原子工作单元。这将(例如)创建客户,订单和订单商品。然后,您可以将所有内容整齐地包装在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 +级别工作并管理原子性它可以“看到”的范围

希望这会有所帮助

编辑:您可能会发现TransactionScope的初始调用(在应用启动时)可能会略微明显(例如,在上面的例子中,如果是第一次调用,可以采取然而,2-3秒完成),后续呼叫几乎瞬时(即通常为250-750毫秒)。简单的联系交易与(笨重的)替代方案之间的权衡减轻了(对我和我的客户而言)最初的“加载”延迟。

只是想表明轻松不会毫不妥协(虽然在初始阶段)

答案 1 :(得分:4)

您所描述的是长期交易的“定义”。

每个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中的任何方法,它负责控制提交。注意:您也可以在短期/常规交易中使用“保存点”。

答案 2 :(得分:2)

好问题。这成为阻抗不匹配的核心。

这是使用存储过程的最强参数之一。原因:它们旨在将多个SQL语句封装在事务中。

同样可以在DAL中以程序方式完成,但它会导致代码的清晰度降低,同时通常会导致耦合/内聚平衡向错误的方向移动。

出于这个原因,我在更简单的抽象层次上实现DAL,而不是简单地封装表格。

答案 3 :(得分:1)

以防我在原始文章中的评论没有“坚持”,这是我添加的其他信息:

< ----- 巧合的是,刚刚注意到你的请求后几个小时发布了另一个类似的引用。使用类似的策略,也值得你看一下: http://stackoverflow.com/questions/494550/how-does-transactionscope-roll-back-transactions ----->