Overriding a DataModel inside a DLL

I have a new MVC project that I am working on that is basically a CMS that I intend to use in other projects, the structure is the following

Overriding a DataModel inside a DLL

let’s say I created a new project that use the DLLs of my CMS, though a client need to add a new tables to the model based on additional criteria’s, what is the best way to override the EcomerceModel.edmx so I can work with the new added table without touching the Original Dlls from the new created project.

Thank you,

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Well, there is a fast solution to this, which is dividing your Data project into several projects to keep it at minimum requirements.

So, if we take your Data project as an example it would be separated into several class libraries something like :

  • Data.Models (would contains only the data models for abstractions purposes).
  • Data.Core (Which is the main data project).
  • Data.Common (Optional)
  • Data.Helpers (Optional)

For this to work probably, you will need to switch to Code First approach, to ensure you’ll have control over your migrations and models. (You don’t need EF to overwrite your customizations every time you update the models, plus you’ll need to keep your updates in the code and not in the database).

it’s recommended to keep your models in separate assembly, to be reused in other projects without the need to reference the full data layer.

After this, in your Data.Core you will need to reference all other Data.* class libraries to it. Then, you can create your DbContext like this :

public class ECommerceDbContext : DbContext 
{
    public DbSet<Admin> Admins { get; set; }
    
    /// rest of Entities 
    

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        
        // your Entities configurations 
    }   
}

Now, your Data layer is set and ready to be referenced in other projects.

In your other projects that you want to reuse the current Data.Core you need to reference Data.Core (either by project reference or Nuget). Then, create a new class that inherits ECommerceDbContext which would extend it. Something like :

public class ECommerceCMSContext : ECommerceDbContext 
{
    /// New Entities 
    

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        
        // New Entities configurations 
    }   
}

Now, work with ECommerceCMSContext to add any new table to the current context.

P.S. You can take a look at ASP.NET Core Identity they’re using similar implementation, which would be very helpful to your work.

Method 2

Your question is not a simple one to answer. You are asking to do data mapping on a programmatic level and depending on how much change you want to overcome/handle will determine how complex the answer must be. This can also be seen as Model Inheritance.

Firstly, the edmx file is useless for what you want to do. It combines the business model with the data model which means any change to data or business model result in a broken file.

Both options below will require a LOT of work and should be considered a totally new application in terms of size.

METADATA SOLUTION

You might want to look at creating a metadata/data layer within your code and using that to change the look of the database.

Instead of accessing the model through ecommerce.edmx – access it through separate business/data layers. The data layer can then create the data accesses / sql using dynamic calls or by using an external preferences file to hold the sql accesses.

i.e.
Create an external file, table in the database or a resource in code with metadata describing the tables you want to use. A very simple solution could look like:

MetaTables (id, myTableName, derivedTableName)
    Order, "Order", "UserOrder"
    Customer, "Customer", "UserCustomer"

MetaAttributes (tableId, id, myAttrName, myAttrType, derivedAttrName, derivedType, etc)
    Order, Id, "Id", int, "UserId", guid
    Order, Description, "Description", string, "UserDescription", string
    Customer, Id, "Id", int, "UserId", guid

MetaRelations ()
    etc

Then use this to create your queries dynamically. If you do it this way others can use your code and only need to update your metadata file with a new mapping. As long as they don’t add new mandatory columns.

Strengths:

  • Can work quickly with any new data structure
  • Data structure can be changed on the fly if required
  • Version independent

Weaknesses:

  • Dynamically created queries can be VERY slow
  • It takes a long time to implement a dynamic data layer

REFLECTION SOLUTION

Another way is to store your data layer in a separate assembly and reference it using interfaces.

All the new application needs to do is to replace your data layer with theirs.

i.e.

public interface IDataLayer
{
    public List<IOrder> GetOrderList()
}

// MyDLL1
public class DataLayerImplementationA: IDataLayer
{
    public List<IOrder> GetOrderList()
    {
        // get data from database X, return results
    }
}

// MyDLL2
public class DataLayerImplementationB: IDataLayer
{
    public List<IOrder> GetOrderList()
    {
        // get data from database B, return results
    }
}

Strengths:
  • Code is designed to work with new database
  • Fastest implementation
  • Compile time checking!

Weaknesses:

  • Requires assembly override with new compiled DLL
  • Multiple DLLs
  • Even a small change will potentially require a lot of coding by a programmer (or cut and pasting at the very least)

WORK AROUNDS

If the modifications are really trivial you could write a parser to edit the mapping data within the edmx files. Not recommended as that could result in instability.

Another work around could include using database views to hide the changes and moving the data change handling to the database. So keep the old edmx file looking at views and the new edmx file with the expanded design looking at the expanded tables.

Work arounds are just that.. they will probably be more pain than they are worth for all but the most trivial changes.

If you want to do some research have a look at articles using terms like

  • Object Orientation Concepts
  • Abstract data layers
  • Model inheritance
  • Model Controller View

Good hunting!


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x