跨多个数据库的DataContext

我有一个应用程序需要将来自多个数据库的表连接到单个LINQ-to-SQL查询中。 不幸的是,我为每个数据库设置了一个单独的DataContext类,因此这个查询不起作用。 我收到这样的错误: “查询包含对在不同数据上下文中定义的项的引用”

理想的解决方案似乎是为所有三个数据库创建单个DataContext。 它们都存在于同一台服务器上,因此它们可以使用相同的连接字符串。 我目前使用运行sqlmetal.exe的脚本来生成我的DBML和CS文件,这意味着我在更改数据模型时不需要手动编辑任何文件。 我想保持这种自动化水平,但sqlmetal.exe似乎只支持每个DBML文件一个数据库。

这可能与sqlmetal或其他工具? 或者,我是否需要考虑另一种解决方案,例如在整个应用程序中使用单个数据库?

这是我正在使用的批处理文件脚本:

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SqlMetal.exe" /server:MYSERVER /database:DatabaseOne /views /functions /sprocs /dbml:DatabaseOne.dbml /namespace:Model.Domain.DatabaseOne /context:DatabaseOneDataContext /pluralize "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SqlMetal.exe" /server:MYSERVER /database:DatabaseOne /views /functions /sprocs /code:DatabaseOne.designer.cs /language:C# /namespace:Model.Domain.DatabaseOne /context:DatabaseOneDataContext /pluralize "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SqlMetal.exe" /server:MYSERVER /database:DatabaseTwo /views /functions /sprocs /dbml:DatabaseTwo.dbml /namespace:Model.Domain.DatabaseTwo /context:DatabaseTwoDataContext /pluralize "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SqlMetal.exe" /server:MYSERVER /database:DatabaseTwo /views /functions /sprocs /code:DatabaseTwo.designer.cs /language:C# /namespace:Model.Domain.DatabaseTwo /context:DatabaseTwoDataContext /pluralize "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SqlMetal.exe" /server:MYSERVER /database:DatabaseThree /views /functions /sprocs /dbml:DatabaseThree.dbml /namespace:Model.Domain.DatabaseThree /context:DatabaseThreeDataContext /pluralize "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SqlMetal.exe" /server:MYSERVER /database:DatabaseThree /views /functions /sprocs /code:DatabaseThree.designer.cs /language:C# /namespace:Model.Domain.DatabaseThree /context:DatabaseThreeDataContext /pluralize 

一位同事在另一个网站 [social.msdn.microsoft.com] 上发现了一个讨论同样问题的post。 一个讨论的解决方案是在“主”数据库中执行视图中的所有连接,并将这些视图公开为应用程序中的对象。 这可能适用于我的情况,因为我的大部分数据都在一个数据库中,而其他数据库中的少量表是只读的。

这听起来有点疯狂,但我只是测试了它,所以试试这个:

  • 为要加入的“外部”表创建自定义实体类,或使用SqlMetal生成类;
  • 转到TableAttribute ,它应该说[Table(Name="dbo.ExternalTable")] ,并将其更改为[Table(Name="DatabaseTwo.dbo.ExternalTable")]
  • 创建一个与“DatabaseOne”DataContext同名的分部类,并在那里添加Table属性,即:

     partial class DatabaseOneDataContext { public Table ExternalTable { get { return GetTable(); } } } 

现在尝试从第一个DataContext运行整个查询:

 DatabaseOneDataContext context = new DatabaseOneDataContext(); var query = from s in context.RealTable join t in context.ExternalTable on s.ID equals t.ID select new { s, t }; Console.WriteLine(query.ToList().Count); 

令人难以置信,它的工作原理。 它并不像使用SqlMetal那么简单,但您只需要编写一次部分类,然后就可以在两个数据库上运行SqlMetal并更改任何外部表的TableAttribute以包含数据库名称。

它并不完美,但它有95%,不是吗?