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

The repository's repository

Ever since I started delving into architecture,  and specifically service oriented architecture, there has been one matter where opinions get divided. Let me state the problem first, and then take a look at both sides of the barricade. Given that your service layer needs to access persistent storage, how do you model that layer? It is almost common knowledge what to do here: use the Repository design pattern. So we look at the pattern and decide that it seems simple enough! Let's implement the shit out of it! Now, let's say that you will use an ORM - here comes trouble. Specifically we're using EF, but we could be talking about NHibernate or really any other. The real divisive theme is this question: should you be using the repository pattern at all when you use an ORM? I'll flat out say it: I don't think you should... except with good reason. So, sharpen your swords, pray to your gods and come with me to fight this war... or maybe stay in the couch? ...

Follow up: improving the Result type from feedback

This post is a follow up on the previous post. It presents an approach on how to return values from a method. I got some great feedback both good and bad from other people, and with that I will present now the updated code taking that feedback into account. Here is the original: And the modified version: Following is some of the most important feedback which led to this. Make it an immutable struct This was a useful one. I can't say that I have ever found a problem with having the Result type as a class, but that is just a matter of scale. The point of this is that now we avoid allocating memory in high usage scenarios. This was a problem of scale, easily solvable. Return a tuple instead of using a dedicated Result type The initial implementation comes from a long time ago, when C# did not have (good) support for tuples and deconstruction wasn't heard of. You would have to deal with the Tuple type, which was a bit of a hassle. I feel it would complicate the ...

C# 2.0 - Partial Types

For those of you interested, i found a very interesting list of features that were introduced in C# in  here . This is a very complete list that contains all the features, and i'm explaining them one by one in this post series. We've talked about  Generics  and  Iterators . Now it's time for some partial types . A partial type  is a type which definition is spread across one or more files. It doesn't have to be in multiple separated files, but can be. This is a very simple concept that can give us many benefits, let's see: If a type is partial, multiple developers can work on every part of it. This allows a more organized way of working and can lead to production improvement.  Winforms , for example, generates a partial class for the form so that the client can separately edit other parts it. This way, a part contains information about the design and the other contains the logic of the form. In fact, this is a very spread pattern across .Net. Ent...