Making an Entity Framework Model span multiple databases

后端 未结 3 1631
终归单人心
终归单人心 2020-11-30 04:06

Is it valid to do something such as

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

and then modify Entity Framework\'s edmx

相关标签:
3条回答
  • 2020-11-30 04:36

    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.

    0 讨论(0)
  • 2020-11-30 04:46

    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.

    0 讨论(0)
  • 2020-11-30 04:48

    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);
        }
    
    0 讨论(0)
提交回复
热议问题