Friday, August 12, 2011

Add a table that was deleted in an Entity diagram

If you have come here, I understand your pain. You deleted a table from a entity diagram for some reason and you have trying in vain to add it back using the "update data model from database" option.

Unfortunately there is no easy way to add it back. For some reason, the people who designed it thought that if a user deleted a entity, why would he want to add it back again? But they forgot there are various reasons why someone would want to do it. For eg, I created a model from a database on server A. The database had a table nemed "Attendees". All the other tables started with a lower case. Now moved my database server to a new server and so I thought its a good time to rename this table for consistency. So I renamed and configured my entity model to refresh from the new server expecting that everything would be alright. But lo and behold, now I had 2 entities in the diagram called "Attendees" and "attendees1". Ok, I understand .. when the wizard could not find a table called "Attendees" instead of deleting the table, it thought it might be a entity I created manually and so left it as it is. When it now a new table with the same name, it just created another entity with "1" attached to the end.
I can solve this by just deleting both the enitities and refreshing the table again. Surprisingly, it was not so easy. When I deleted and refreshed, the "attendee" table would no longer appear. What I found is that it just deletes from the designer, but keeps a reference to the table.
Ok, again I understand the reason why the designer leaves the reference is because how else will the designer figure out other entities that I have actually deleted from the diagram, but still have same tables in the database? But I think they could have built that function in the wizard so the user can decide on what tables he would not like in the diagram and what tables he would like to add again.

Anyway, back to what this post is all about. How will I add this table back again? There are 2 options and both options involve editing the edmx file

     Option 1) Delete all reference to "attendees" entity in the diagram
     Option 2) Add the "attendees" reference to the places where it might be missing so the designer adds it back.

Option 1 would be tricky if you have lots of references for that table and the table design is complex.
In my case, I opted for option 2 because I thought adding a reference back to the designer would be easy for me.
Option 1 is pretty straight forward and so I will not discuss on how to go about doing it
For option 2, you will have to do the following....
There are 3 main sections in the edmx file
  1. Storage model - a refernce to all the tables
  2. Conceptual model - entities that are part of the entity model
  3. Mapping - entity properties to database column mapping
The missing table "attendees" was missing in the sections conceptual model and mappings.

Step 1: Add missing enity in conceptual model
Copy the attendees tag from Storage model
<EntitySet Name="attendees" EntityType="MyModel.Store.attendees" store:Type="Tables" Schema="dbo" />

into the tag within  "EntityContainer". Remember to make the changes like removing attributes not needed and also removing the ".store" from the namespace. For my case the tag I added would look like this
<edmx:ConceptualModels>
  <Schema Namespace="MyModel" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
   <EntityContainer Name="MyEntities">
      <EntitySet Name="attendees" EntityType="MyModel.attendees" />

Step 2: Add missing entity tag to conceptual model
Copy the attendees entity tag and its contents from storage model
<EntityType Name="attendees">
<Key>
  <PropertyRef Name="attendees_id" />
</Key>
    <Property Name="attendees_id" Type="bigint" Nullable="false" StoreGeneratedPattern="Identity" />
    <Property Name="Column1" Type="bigint" Nullable="false" />
    <Property Name="Column2" Type="varchar" Nullable="false" />
    <Property Name="Column3" Type="bit" Nullable="false" />
    <Property Name="Column4" Type="dateime" Nullable="false" />
</EntityType>

as a new entity type under the ConceptualModel\Schema tag .. It will look something like this
<edmx:ConceptualModels>
<Schema Namespace="MyModel" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
   <EntityType Name="attendees">
    <Key>
      <PropertyRef Name="attendees_id" />
    </Key>
     <Property Name="attendees_id" Type="Int64" Nullable="false" />
     <Property Name="Column1" Type="Int64" Nullable="false" />
     <Property Name="Column2" Type="String" Nullable="false" />
     <Property Name="Column3" Type="Binary" Nullable="false" />
     <Property Name="Column4" Type="DateTime" Nullable="false" />
  </EntityType/>
Note, I made changes to the types of the columns .. for eg, all bigint are Int64, varchar as string, bit as binary. I also removed any other attributes that are not needed like StoreGeneratedPattern="Identity" from the primary key "attendees_id"

Step 3: Add the mapping
Add the mapping as below
<edmx:Mappings>
  <Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
      <EntityContainerMapping StorageEntityContainer="MyModelStoreContainer" CdmEntityContainer="MyEntities">
         <EntitySetMapping Name="attendees">
            <EntityTypeMapping TypeName="IsTypeOf(MyModel.attendees)">
               <MappingFragment StoreEntitySet="attendees">
                  <ScalarProperty Name="attendees_id" ColumnName="attendees_id" />
                  <ScalarProperty Name="Column1" ColumnName="Databasecolumn1" />
                  <ScalarProperty Name="Column2" ColumnName="Databasecolumn2" />
                  <ScalarProperty Name="Column3" ColumnName="Databasecolumn3" />
                  <ScalarProperty Name="Column4" ColumnName="Databasecolumn4" />
               </MappingFragment>
         </EntityTypeMapping>
       </EntitySetMapping>
For this change, note that you need to add a mapping for each column in your database

Step 4: Get all other relations for the table
Its quite possible that you had other relations for this with other database tables and that is the reason you opted for option1 instead of option2. For this you just need to open the designer again, right click and select the "Update model from database" option and Viola! all the other relations and mappings are automatically added ..
Hope this helps ..