如何处理BL中的嵌套数据上下文?

public class TestBL
{
    public static void AddFolder(string folderName)
    {
        using (var ts = new TransactionScope())
        {
            using (var dc = new TestDataContext())
            {
                var folder = new Folder { FolderName = folderName };

                dc.Folders.InsertOnSubmit(folder);
                dc.SubmitChanges();

                AddFile("test1.xyz", folder.Id);
                AddFile("test2.xyz", folder.Id);
                AddFile("test3.xyz", folder.Id);

                dc.SubmitChanges();
            }

            ts.Complete();
        }
    }

    public static void AddFile(string filename, int folderId)
    {
        using (var dc = new TestDataContext())
        {
            dc.Files.InsertOnSubmit(
                new File { Filename = filename, FolderId = folderId });

            dc.SubmitChanges();
        }
    }
}

这是嵌套的DataContext(未经测试)的示例。 当TransactionScope添加到我们的小实验中时,问题就开始了(如上所示)。 AddFolder函数中的第一个AddFile会将事务升级为DTC(这一切都很糟糕),因为AddFile初始化新的DataContext,从而打开到DB的第二个连接。

  • 我怎样才能使用不会出现DTC使用的嵌套的DataContext?
  • 这完全是错的吗? 我应该以不同的方式使用DataContext吗?

  • 无疑尽可能避免升级到DTC。 当我第一次看到你的问题时,我的直觉说你的交易不会升级到DTC,因为你在两个数据上下文中都使用了相同的连接字符串。 不过,根据这篇文章,我错了。

    对于数据上下文的最佳实践,您并不孤单。 如果你在网上搜索这个,那么地图上会有答案。 在你的例子中,你可以将数据上下文传递给AddFile方法。 或者,您可以将此数据访问重构为维护数据上下文生命周期的类,直到文件夹和文件都保存完毕。 Rick Strahl发表了一篇关于几种技术的文章。

    尽管如此,我在LINQ to SQL中看到的所有答案都看起来非常令人满意。 您是否考虑过使用ORM避免对数据层进行管理? 我已经使用NetTiers获得了巨大成功,但我听到了有关PLINQO的好消息。 这两个都需要CodeSmith,但有很多选择。


    除了将DataContext作为参数传递给AddFiles外,还可以将一个DataContext的Connection值传递给另一个DataContext。 这将保证其他DataContext具有相同的连接。

    每个DataContext也有一个Transaction属性,你可以设置和传递,而不是使用TransactionScope对象。


    我想出了一种处理这种情况的方法。

    BL实体的示例基类(实体将继承此类)

    abstract public class TestControllerBase : IDisposable
    {
        public TestDataContext CurrentDataContext { get; private set; }
    
        protected TestControllerBase()
        {
            CurrentDataContext = new TestDataContext();
        }
    
        protected TestControllerBase(TestDataContext dataContext)
        {
            CurrentDataContext = dataContext;
        }
    
        protected void ClearDataContext()
        {
            CurrentDataContext.Dispose();
            CurrentDataContext = new TestDataContext();
        }
    
        public void Dispose()
        {
            CurrentDataContext.Dispose();
        }
    }
    

    实施控制器

    public sealed class BLTestController : TestControllerBase
    {
        public BLTestController() { }
    
        public BLTestController(TestDataContext dataContext)
            : base(dataContext) { }
    
        //  The entity functions will be implemented here using CurrentDataContext
    }
    

    简单使用已实施的控制器

    var testController = new BLTestControllerA();
    
    testController.DeleteById(1);
    

    更复杂的实现控制器的使用(2个控制器在同一个DataContext上)

    var testControllerA = new BLTestControllerA();
    var testControllerB = new BLTestControllerB(testControllerA.CurrentDataContext);
    
    testControllerA.DeleteById(1);
    testControllerB.DeleteById(1);
    

    我希望看到更多关于解决这个谜题的想法和关于上述代码的评论。

    链接地址: http://www.djcxy.com/p/43113.html

    上一篇: How to handle nested datacontext in the BL?

    下一篇: Java temp files and automated deletion