【问题标题】:Entity Framework: Linq !contains based on table from different database实体框架:Linq !包含基于来自不同数据库的表
【发布时间】:2015-03-21 14:05:20
【问题描述】:

使用实体框架,我试图解决 Linq 无法处理来自不同数据库的表之间的连接这一事实。数据库:

DB1.dbo.Table1:Id,XmlText

DB2.dbo.Table2:Id、TimeStamp、ColA、ColB...

我想在Table2中找到XmlText中某个属性设置为true的行,即XmlText包含'xmlProp=true'

在 SQL 中,我会简单地写

SELECT *
FROM [DB2].[dbo].[Table2]
INNER JOIN [DB1].[dbo].[Table1] ON [Table1].Id = [Table2].Id
WHERE XmlText like '%xmlProp=true%'

由于我不能在 Linq 中使用 join(不同的数据库,记得吗?),我正在这样做:

var query = from t1 in db1.Table1
    where db1.Text.Contains('<xmlProp>false</xmlProp>)
    select t1.Id;

var set = new HashSet<Guid>();
foreach (var elem in query)
    set.Add(elem);

var query2 = from t2 in db2.Table2
    where !set.Contains(t2.Id)
    select t2;

我当然可以搜索 'true',但更少的行有 false,所以集合会更小,从而提高性能。

现在:有没有更好的方法来做到这一点?生成的 SQL 查询非常庞大(要避免的一长串 ID ......),将 ID 存储在内存中只是为了再次将它们传回 SQL 服务器感觉很愚蠢。有人吗?

谢谢, M

【问题讨论】:

  • stackoverflow.com/questions/352949/… 您需要定义要针对特定​​表访问的数据库,或者提供两个不同的数据上下文,以便您可以辨别哪个 database.table 是哪个。
  • 意识到我忘了提到我正在使用实体框架......所以我没有 dbml 文件可以按照您的链接中的建议进行编辑。另外,我不能在一个查询中使用两个上下文,对吧?

标签: sql-server database linq join contains


【解决方案1】:

您可以使用两个 DataContext,或者如果它们位于同一服务器下,您可以设置视图和 3 部分命名,以便一个数据库可以进行调用。

但是正如您之前所说的,在一个查询中不能有两个上下文,当实际执行发生时,您不能将它们混合在一起。

您可以使用两个 DataContext,您只需确保它们在连接之前被执行并被带到内存中,然后只需连接内存中的实体即可。我知道这不如推迟执行直到实际枚举发生,特别是如果您将大量信息带入内存并进行大量过滤,因为迭代一次集合比重复传递要好得多,但这应该会让您得到正确的答案离开。

只需将服务器、数据库和表名替换为您环境中的任何名称。

您从不同上下文引用项目但失败的示例:

void Referencing_Both_In_One_Query()
{
    const string sc1 = @"Server=YOURSQLSERVER;Database=DEVDATABASE1;Trusted_Connection=True;";
    const string sc2 = @"Server=YOURSQLSERVER;Database=DEVDATABASE2;Trusted_Connection=True;";

    using (var dc = new DataContext(sc1))
    {
        using (var dc2 = new DataContext(sc2))
        {
            var users1 = dc.GetTable<Users>();
            var users2 = dc2.GetTable<Users>();

            //You'll get some error saying the query contains references to items defined on a different data context.
            var joined = (from u1 in users1
                join u2 in users2 on u1.Login equals u2.Login
                select u2.Login);

            joined.ToList(); //<< Execution happens here when we enumerate. and it's executing across 2 different data contexts.            
        }
    }
}

这是另一个在连接之前枚举的示例:

void Enumerating_Then_Joining()
{
    const string sc1 = @"Server=YOURSQLSERVER;Database=DEVDATABASE1;Trusted_Connection=True;";
    const string sc2 = @"Server=YOURSQLSERVER;Database=DEVDATABASE2;Trusted_Connection=True;";

    using (var dc = new DataContext(sc1))
    {
        using (var dc2 = new DataContext(sc2))
        {
            var users1 = dc.GetTable<Users>().Select(x => x).ToList();  //<< Enumerate here executing on your datacontext 1
            var users2 = dc2.GetTable<Users>().Select(x => x).ToList(); //<< Enumerate here executing on your datacontext 2

            // now we work on the in memory entities.
            var joined = (from u1 in users1
                        join u2 in users2 on u1.Login equals u2.Login
                        select u2.Login);

            joined.ToList();    
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-12
    相关资源
    最近更新 更多