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
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