【问题标题】:Making an Entity Framework Model span multiple databases使实体框架模型跨越多个数据库
【发布时间】:2011-08-27 12:57:09
【问题描述】:

这样做是否有效,例如

CREATE SYNONYM [dbo].[MyTable] FOR [AnotherDatabase].dbo.[MyTable]

然后修改 Entity Framework 的 edmx 文件以读取此对象,就像读取任何其他表一样?

我做了一个快速的示例测试,它似乎可以很好地选择和更新,但我想知道是否有任何理由不应该这样做

我通过创建指向第二个数据库的 edmx 文件来获取表定义,在那里构建实体,然后将定义复制/粘贴到第一个数据库的 edmx 文件中。

更新

如果有人感兴趣,我会写下我为使 edmx 文件跨越多个数据库 here 所做的工作。它包括用于生成同义词和合并 edmx 文件的脚本。

【问题讨论】:

  • 我看到的主要缺点是需要手动操作 edmx,并且无法自动更新 edmx 以引入数据库模式更改。可能还有其他缺点。
  • @carmainc:这是一个小烦恼,但对我来说,它比必须手动创建两个数据上下文之间的链接以及必须多次访问服务器以获取链接数据要好得多。相反,我只需要更新我的第二个 edmx 文件并复制/粘贴新信息。
  • 瑞秋,我看到了你的帖子。我想知道您是否遇到了除了您的帖子中已经列出的问题之外的问题...我正在考虑您为我工作的公司正在开发的 ERP 的方法...谢谢!!!
  • 很高兴你喜欢它!我还没有遇到任何问题,但我也没有将它用于任何高级的东西,因为我自己对 EF 还很陌生。我知道有一天需要修复的唯一一件事是合并脚本需要考虑已删除的项目。我知道如何修复它,但我没有费心去实际更新脚本,因为我还不需要它
  • 你是一个救生员! :)

标签: sql-server entity-framework multiple-databases synonym


【解决方案1】:

我发现这个带有同义词的技巧完美适用于“代码优先”方法,无需对 edmx 文件进行任何操作!

您唯一需要做的就是将您的类“绑定”到 DataContext 的 OnModelCreating 方法中的适当同义词。

例如, 如果我在另一个 DB 中有表 Personnel 的同义词(并且类名也是 Personnel),并且同义词的名称是 "myschema.MySynonym" 那么 OnModelCreating 方法应该如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("myschema");

        modelBuilder.Entity<Personnel>()
            .ToTable("MySynonym");

        Database.SetInitializer<TestSynonymContext>(null);

        base.OnModelCreating(modelBuilder);
    }

【讨论】:

    【解决方案2】:

    您也可以使用视图来执行此操作(如果另一个数据库位于不同的服务器上,则使用链接服务器)。这将使您不必管理/合并两个单独的 edmx 文件。我已将此与链接服务器一起用于从另一台服务器上的第二个数据库读取数据,但运行了一些快速测试以查看是否可以进行更新/插入/删除。

    我对分布式事务的经验为零,因此与分布式事务相关的信息可能是好的、坏的或两者兼而有之。 如果您的两个数据库都打开我假设分布式事务不再适用的同一服务器。

    在使用链接服务器时需要牢记几件事。

    1. 当您修改链接数据库表中的实体并在您的上下文中调用 SaveChanges 时,这将尝试启动分布式事务,因此除非有人知道如何停止该事务,否则您需要确保将两台服务器设置为处理分布式事务。 (我认为使用同义词也是如此)。
    2. 在链接服务器上具有标识列的实体上插入会引发异常,因为 ef 尝试使用 SCOPE_IDENTITY() 获取新 id 并且它为 null。我不知道有没有办法解决这个问题。我在使用标识列的链接服务器上更新或删除实体时没有任何问题。

    在 SQL Server A 上

    1. 创建与 ServerB 的链接服务器(如果 db 位于同一服务器上,则跳过此步骤)。
    2. 在[ServerA].[MyDB] 中为您要访问的[ServerB].[AnotherDB] 中的每个表创建一个视图

    在 EDMX 中

    1. 将您的视图添加到 edmx 文件中
    2. 从设计器中的每个属性中清除实体键设置(包括实际的pk)
    3. 为实际pk重置实体键
    4. 根据需要添加关联
    5. 保存更改

    更新/插入/删除

    1. 右键单击您的 edmx 文件并使用 xml 编辑器打开
    2. 导航到StorageModel -> Schema -> EntityContainer
    3. 为您的实体找到实体集并删除DefiningQuery 元素
    4. 在实体集上找到store:Schema 属性并删除store:,使其只是Schema。别管它的价值。
    5. 对来自链接服务器的每个视图重复第 3 步和第 4 步
    6. 保存更改

    因为使用链接服务器创建了一个分布式事务,所以在 SaveChanges 成功之前,我必须在 ObjectContext 上做几件事。

    ctx.Connection.Open();
    ctx.ExecuteStoreCommand("set xact_abort on");
    ctx.SaveChanges();
    ctx.Connection.Close();
    

    您可能可以创建一个自定义 ObjectContext 并覆盖 SaveChanges 以添加这些内容。

    【讨论】:

    • 那是我不想做的……这是一大堆额外的工作。您需要创建视图、创建 PK、查找和修改 DefiningQuery,并重新创建链接数据库中存在的任何链接。我宁愿只更新我的 EDMX 文件并运行一个合并脚本(使维护变得简单易行,即使对于那些对 EF 不太了解的人也是如此)。如果您的数据库不支持同义词,这是很好的信息。
    【解决方案3】:

    如果你做了一个测试并且它成功了,你可能展示了一些其他人不知道的东西。到目前为止,我总是回答这类问题:不可能将单个模型与两个数据库一起使用(基于视图隐藏第二个数据库中的表的一些更丑陋的解决方法)。现在我知道了两种解决方法。

    这种方法的唯一缺点是,如果您运行从数据库更新模型,手动对 EDMX 的 SSDL 部分所做的所有更改都会丢失。这意味着要么手动开发 EDMX(这是一项非常艰巨的工作),要么使用一些工具/脚本在每次从数据库更新后添加您的更改。

    【讨论】:

    • 你不知道的事实让我觉得这个想法有问题......我以为你知道关于 EF 的一切! :) 谢谢你
    • 这更多是关于了解数据库服务器的功能,我真的对EF一无所知。我还在学习...
    • 我实际上编写了一个脚本,该脚本将合并 edmx 文件而不会覆盖您所做的更改。所以我的最终结果是一个项目持有我的工作 edmx,一个项目持有我的第二个数据库的 edmx,第三个项目运行一个将 edmx#2 与 edmx#1 合并的脚本。
    • @Rachael,这正是我刚刚实现的(将两个 edmx 合并为一个新的第三个),我估计它可以工作,但直到现在还没有任何证据。 :-)
    猜你喜欢
    • 1970-01-01
    • 2017-10-04
    • 2011-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多