使实体框架模型跨越多个数据库

时间:2011-05-17 19:56:39

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

执行

之类的操作是否有效

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

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

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

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

更新

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

3 个答案:

答案 0 :(得分:11)

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

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

答案 1 :(得分:2)

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

我对分布式事务没有任何经验,因此与分布式事务相关的信息可能是好的,坏的,或者两者兼而有之。 如果你的两个数据库都打开了我 ASSUME 分布式交易的同一台服务器不再适用。

使用链接服务器时需要注意几点。

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

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

      1. 将您的观点添加到edmx文件
      2. 清除设计器中每个属性的实体键设置(包括实际的pk)
      3. 重置实际pk的实体密钥
      4. 根据需要添加关联
      5. 保存更改
      6. 有关更新/插入/删除

        1. 右键单击您的edmx文件并使用xml编辑器打开
        2. 导航至StorageModel - > Schema - > EntityContainer
        3. 找到实体的实体集并删除DefiningQuery元素
        4. 在实体集上找到store:Schema属性,然后移除store:,使其仅为Schema。保持其价值。
        5. 重复步骤3& 4来自链接服务器的每个视图
        6. 保存更改
        7. 由于使用链接服务器创建分布式事务,我必须在ObjectContext成功之前在SaveChanges上执行一些操作。

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

          您可以创建自定义ObjectContext并覆盖SaveChanges以添加此内容。

答案 2 :(得分:0)

我发现这个带有同义词的诀窍完全与" Code first"没有任何edmx文件操作的方法!

你唯一需要做的就是"绑定"您的类在DataContext的OnModelCreating方法中适当的同义词。

例如, 如果我在另一个数据库中有表人员的同义词(并且类名也是人事部门),并且同义词& #39;的名称是" myschema.MySynonym" 然后OnModelCreating方法应如下所示:

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

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

        Database.SetInitializer<TestSynonymContext>(null);

        base.OnModelCreating(modelBuilder);
    }