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

发布于 2024-11-08 16:32:43 字数 497 浏览 6 评论 0原文

执行诸如

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

之类的操作,然后修改实体框架的 edmx 文件以像读取任何其他对象一样读取此对象 是否有效桌子?

我做了一个快速示例测试,它似乎适合选择和更新,但我想知道是否有任何原因我不应该这样做

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

更新

如果有人感兴趣,我写了我如何制作跨多个数据库的 edmx 文件 此处。它包括用于生成同义词和合并 edmx 文件的脚本。

Is it valid to do something such as

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

and then modify Entity Framework's edmx file to read this object like it would any other table?

I did a quick sample test and it seems to work fine for selecting and updating, but I wanted to know if there was any reason why I shouldn't be doing this

I am getting the table definition by creating an edmx file pointing to the 2nd database, building out the entities there, then copy/pasting the definition into the 1st database's edmx file.

UPDATE

If anyone is interested, I wrote up what I did to make an edmx file span mulitple databases here. It includes scripts for generating synonyms and merging edmx files.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瑕疵 2024-11-15 16:32:43

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

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

If you made a test and it worked you probably showed something nobody else know about. Till now I always answered this type of question: It is not possible to use single model with two databases (with some more ugly workaround based on views hiding tables from the second database). Now I know two workarounds.

The only disadvantage of this approach is that all changes made manually to SSDL part of your EDMX are always lost if you run Update model from database. This means either manual development of EDMX (which is quite hard work) or using some tool / script which will add your changes after each update from database.

乱了心跳 2024-11-15 16:32:43

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

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

使用链接服务器时需要记住以下几点。

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

在 SQL Server A

  1. 创建一个到 ServerB 的链接服务器(如果数据库位于同一服务器上,则跳过此步骤)。
  2. [ServerA].[MyDB] 中为您想要

在 EDMX

  1. 访问的 [ ServerB ].[AnotherDB] 中的每个表创建一个视图您对 edmx 文件的视图
  2. 清除设计器中每个属性的实体键设置(包括实际的 pk)
  3. 重置实际 pk 的实体键
  4. 根据需要添加关联
  5. 保存更改

用于更新/插入/删除

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

因为使用链接服务器会创建分布式事务,所以在 SaveChanges 成功之前,我必须在 ObjectContext 上执行一些操作。

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

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

You can also do this with views (and a linked server if the other db is on a different server). This will keep you from having to manage/merge two separate edmx files. I've used this with a linked server for reading data from a second db on a different server but ran a few quick tests to see if updates/inserts/deletes were possible and they are.

I have zero experience with distributed transactions so the info related to distributed transactions may be good, bad, or a little bit of both. If your two db's are on the same server I ASSUME distributed transactions no longer apply.

There are a couple of things to keep in mind when using a linked server.

  1. When you modify the entities in the linked db tables and call SaveChanges on your context, this will try to start a distributed transaction so unless anyone knows how to stop that, you need to make sure the two servers are setup to handle distributed transactions. (I would assume this would be true using synonyms too).
  2. Inserts on entities with identity columns on the linked server throw an exception because ef tries to get the new id using SCOPE_IDENTITY() and it is null. I don't know if there is a way around this. I didn't have any problems updating or deleting entities on the linked server with identity columns.

On SQL Server A

  1. create a linked server to ServerB (skip this if db's are on the same server).
  2. create a view in [ServerA].[MyDB] for each table in [ServerB].[AnotherDB] you want to access

In EDMX

  1. Add your views to the edmx file
  2. Clear the entity key setting from each property in the designer (including the actual pk)
  3. Reset the entity key for the actual pk
  4. Add associations as needed
  5. Save changes

For Updates/Inserts/Deletes

  1. right click on your edmx file and open with xml editor
  2. Navigate to the StorageModel -> Schema -> EntityContainer
  3. Find the entityset for your entity and delete the DefiningQuery element
  4. Find the store:Schema attribute on the entity set and remove store: so that it is just Schema. Leave its value alone.
  5. Repeat steps 3 & 4 for each view from the linked server
  6. Save changes

Because using a linked server creates a distributed transaction I had to do a couple of things on the ObjectContext before SaveChanges was successful.

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

You can probably create a custom ObjectContext and override SaveChanges to add this stuff in.

明天过后 2024-11-15 16:32:43

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

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

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

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

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

        Database.SetInitializer<TestSynonymContext>(null);

        base.OnModelCreating(modelBuilder);
    }

I've found that this trick with synonyms works perfectly with the "Code first" approach without any manipulation with edmx files!

The only thing you have to do, is to "bind" your class to appropriate synonym in the OnModelCreating method of your DataContext.

For example, if I have a synonym to table Personnel in another DB (and the class name is also Personnel), and synonym's name is "myschema.MySynonym" then the OnModelCreating method should looks like:

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

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

        Database.SetInitializer<TestSynonymContext>(null);

        base.OnModelCreating(modelBuilder);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文