如何处理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。 当我第一次看到你的问题时,我的直觉说你的交易不会升级到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