Skip to main content

Entity Framework–Multiple Database support

One of the limitations that EF still has is the support for multiple databases. It simply does not support that option.out of the box. Allthough on UserVoice a lot of people have voted this feature, it still doesn’t exist.

Credit where credit is due: this is not my original idea. I first downloaded the original script, used it and then i almost completely rewrote it to suit my needs and to improve certain aspects. I love Linq, so i used it a lot. The original and fantastic script can be found here

The trick is making EF believe that those objects are in the database by using synonyms. I dont know if every EF-supported database allows synonyms or not, but this is possible in SQL Server (which i am using).  

My script adds the ability to backup the edmx files first (which i find useful to prevent my model from being corrupted), replace the prefixes in the resulting model (which i had to do by hand with the other script) and finally reorder the navigation properties by alphabetical order. This last one is a must for me, because i use LINQPad a lot and the properties appear as links in the order they are declared. Another change include the ability to import the Function Imports declared (if i’m not mistaken the original script would throw an exception for the lack of an attribute in the FunctionImport element)

The following procedures must be taken for this approach to work. I know it seems a lot, but you may benefit much more from it.
  • Define a database that will have all the synonyms for other database objects. This will be your entry point in EF. It can be any database
  • Create synonyms for all foreign objects on your previously defined database. I find it useful to generate a script for the effect which selects a string for every table and then create those synonyms from the script results. Here it is:


  • Create one model for each database you want to merge.

  • Configure the variables in the script. You need to configure the directory of your models, the backup destination and the result file path. There still are similarities with the original script in this. Your can pass as many database paths as you like. Don’t forget to change the XNamespace’s in the begining of the script. They can vary depending on your EF version.

  • Go to the method ReplacePrefixes and configure the variable “CorrectPrefix”. This variable should contain the name of the Conceptual Model of your Main model, the one you created for your entry database. Finally, add new replaces for your other databases in the line where the replace happens.

  • Backup everything manually to a safe location first. Things can go wrong.

  • Run the script, open and validate your principal edmx to check if everything went smooth. 

Limitations
  • The script is a workaround to when you need this kind of feature. It’s a shame EF doesn’t support this, and we have to live with that. Entities will not be removed from the main edmx if they were deleted from any leaf module. I didn’t need this feature, so i didn’t implement it.

  • I cannot garantee that this script will work in all cases. The model i use is not that complex and doesn’t cover all use cases, so some features may be missing.

  • Navigation properties between entities from the merged models are supported. Just be sure you name them with the “LNK_” prefix. This allows me to verify while merging and to keep those rather than overwrite them. My approach is exactly the same as the original script. If you prefer, you can change this prefix in the MergeEDMX method.

  • Take care with objects with the same name between models. If a conflict should exist, your model will become corrupted and you have to modify it manually or restore backups.

  • When you have to import the model from the database, do it always on the leaf models (except when you are importing from the database of your main model, of course) and then merge it.

  • Every time a change occurs in one of the leaf models, you need to merge it again with the main model.

Enough talk! Here is the script, make good use of it!



Disclaimer: Remember to test the script before using it. This is a workaround and is not perfect, may contain bugs or unexpected behavior. Use at your own risk.

Keep coding.

Comments

Popular posts from this blog

From crappy to happy - refactoring untestable code - an introduction

I started testing my code automatically a couple of years in after starting my career. Working in a small company, there weren't really incentives for us to automate testing and we were not following any kind of best practices. Our way of working was to write the code, test it manually and then just Release It ™ , preferably on a Friday of course. I'm sure everyone can relate to this at some point in their career, because this is a lot more common than the Almighty Programming Gods of the Internet make us believe. I find that the amount of companies that actually bother writing tests for their production code is a fraction of the whole universe. I know some friends who work in pretty big companies with big names in the industry and even there the same mindset exists. Of course, at some point in time our code turned into a big pile of shit . Nobody really knew what was going on and where. We had quantum-level switcheroo that nobody really wanted to touch, and I suspect it i...

Why is the Single Responsability Principle important?

The Single Responsability Principle is one of the five S.O.L.I.D. principles in which i base my everyday programming. It tells us how a method or class should have only one responsability. Not a long time ago i was designing a reporting service with my colleague Nuno for an application module we were redoing and we had a method that was responsible for being both the factory method of a popup view and showing it to the user. You can see where this is going now... I figured out it would not be a that bad violation of the principle, so we moved on with this design. The method was called something like "ShowPrintPopup" and it took an IReport as an argument. All this was fine, but then we got to a point where we needed to have a permissions system to say if the user was able to export the report to Excel, Word, PDF, etc... The problem was the print popup would need to know beforehand if it would allow the user to export the report or not, so that it could show it's UI a...

My simplest and most useful type

I have been doing some introspection on the way I write code to find ways that I need to improve. I consider this a task that one must do periodically so that we keep organized. There is a very, very simple problem that occurs in every application I know: How to return the results of an operation to the user? I've seen many implementations. Some return strings, some throw exceptions, some use out parameters, reuse the domain classes and have extra properties in there, etc. There is a myriad of ways of accomplishing this. This is the one I use. I don't like throwing exceptions. There are certainly cases where you have no choice, but I always avoid that. Throughout my architectures there is a single prevalent type that hasn't changed for years now, and I consider that a sign of stability. It is so simple, yet so useful everywhere. The name may shock you, take a look: Yes, this is it. Take a moment to compose yourself. Mind you, this is used everywhere , in every ...