我有一个应用程序需要将来自多个数据库的表连接到单个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
答案 0 :(得分:2)
一位同事发现a thread on another site [social.msdn.microsoft.com]讨论了同样的问题。一个讨论的解决方案是在“主”数据库中执行视图中的所有连接,并将这些视图公开为应用程序中的对象。这可能适用于我的情况,因为我的大部分数据都在一个数据库中,而其他数据库中的少量表是只读的。
答案 1 :(得分:1)
这听起来有点疯狂,但我刚试过它,所以试试这个:
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%,不是吗?