2009-12-15 63 views
2

我有一个应用程序需要将多个数据库中的表连接到一个LINQ-to-SQL查询中。不幸的是,我为每个数据库都有单独的DataContext类设置,所以这个查询不起作用。我得到这样的错误:“查询包含对在不同数据上下文中定义的项目的引用”跨多个数据库的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 
+0

我找到了一个可能适用于我的答案,但我仍然对更高级别的修补程序感兴趣。换句话说,ubersqlmetal。 – MikeWyatt 2009-12-15 23:13:43

回答

2

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

1

这是要听起来有点疯狂,但我只是测试它,那么试试这个:

  • 你要加入,或使用SqlMetal到“外部”表创建一个自定义实体类生成类;
  • 转到TableAttribute,应该这样说[Table(Name="dbo.ExternalTable")],并将其更改为[Table(Name="DatabaseTwo.dbo.ExternalTable")]
  • 具有相同的名称为“DatabaseOne” DataContext的创建一个部分类,并添加Table<T>财产存在,即:

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

现在尝试运行整个查询断第一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%,不是吗?

+0

这很有趣,但它仍然需要一些工作来完全自动化(如你所说)。如果在主数据库中创建视图失败,我会给它一个镜头。 – MikeWyatt 2009-12-16 14:06:20

+0

您可以编写一个简短的脚本,您只需提供两个CS文件(由SqlMetal生成)以及想要“导入”的表名称,然后让它自动生成部分类和实体。前者是一个文本模板,后者只是一个字符串。替换,所以你最终会得到完全自动化的东西。但是,如果您控制数据库并且不介意创建跨数据库视图,那么从长远来看,这将更容易管理。 – Aaronaught 2009-12-16 15:21:55