29

做某事是否有效,例如

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

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

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

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

更新

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

4

3 回答 3

11

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

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

于 2011-05-17T20:04:04.043 回答
2

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

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

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

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

在 SQL Server A 上

  1. 创建一个到 ServerB 的链接服务器(如果数据库在同一台服务器上,请跳过此步骤)。
  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. 保存更改

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

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

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

于 2011-05-25T16:03:48.460 回答
1

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

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

例如,如果我在另一个数据库中有一个表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);
    }
于 2017-12-09T18:05:48.890 回答