Need to generate EDMX files and compile them - c#

My question might be little bit different or basic for advanced users here.
I have a web application which is customizable by administrators. This means, the admin can add new table schema or edit table columns, add new table columns etc. These changes are mapped to our logical objects (much similar to EDMX) which is published after the change. While publishing we generate Stored procedures with necessary changes that are required.
From UI we use these Logical objects to connect DB (using COM which understands the mapping and executes appropriate sprocs and views etc). Now i am thinking to use EF for replacing the Logical objects model which we are having currently. I can create the EDMX files (csdl,msl, ssdl, cs files) dynamically but i am not sure how to compile them and package the classes into DLL dynamically. This means, when i click the button the all edmx related files will be created and DLLs must be created based on CS files and the website must be able to access the new changes in the code.
Can you help me how to automatically and dynamically compile the cs files. I will not have the source code of other files (like default.aspx and others) at customer's end.
Thanks
Albert

Bepenfriends - rather than attempting a CSC from a shell, consider using a CSharpCodeProvider.CompileAssemblyFromFile.
One thing to be careful of: if you compile code and then try to compile it again, you may lock up on the assembly that was created. For this I created an AsyncCompiler which creates a new AppDomain, compiles in there, and then unloads the AppDomain.
It's some pretty hairy code but I'm doing this (generating the AEF XML files, generating code from them, and then compiling everything into an assembly) and it works well. The only thing I don't have quite right is dynamically importing stored procedures - my SSDL has them but not the CSDL or MSL. The search for a solution led me here.
I hope the keywords here are enough to set you off in the right direction.

I don't really have a definitive answer for you just yet - but two potential solutions you could look into, possibly in the near future:
1) There's a set of CodeSmith templates called PLINQO which generate your Linq-to-SQL model (DBMX) and its associated *.cs files from your database. I asked them about Entity Framework support myself, and they confirmed to be working on it - so maybe they'll have that some time soon.
Since those are code and model generation templates, you could definitely take those for Linq-to-SQL and tweak them for EDMX, too. A bit of work, but definitely possible. Once you have the *.cs files and the *.edmx model, you can generate a resulting assembly from it using the CSC (C#) command-line compiler that's installed on every machine which has .NET installed.
2) With .NET 4, the new Entity Framework 4 will include T4 templates (another code generation technology) which will allow you to customize your code generation. Same story applies here - you could externally generate your EDMX model and associated *.cs files for the classes and generate an assembly on the fly from those templates.
See another blog post on that topic, and you should find lots of information when gooling (or binging) or "EF4 T4 templates".
Hope that helps at least a little bit!

Related

Customize T4 template - ADO.Net Entity data model for EF code first from existing database

I am trying to locate and customize the T4 template of ADO.Net Entity data model for EF code first from existing database.
What I want to customize or change is data type mapping. I am using Oracle's ODP.Net provider which supports EF. I am trying to remap the Oracle data type number to Int64 instead of Decimal due to my requirement.
As I am new to editing T4 files for customization I am finding difficulty in locating the template file that does the code first mapping. Any help in pointing me to the right direction is appreciated.
UPDATE Feb 2017: You should check out this amazing EntityFramework Reverse POCO Code First Generator project which consists of T4 templates to do Code First from an Existing Database.
Those templates are very easy to use, fully customizable, and I could easily add my customizations to those templates! Not to mention that they are much more complete than the original EF wizard. The authors/contributors of that project are very friendly and responsive, and I have myself made a few contributions.
_
(Turns out that I was reinventing the square wheel by creating my own T4 templates).
Original Answer (just for reference if helps anyone digging into EF Wizard source code):
I don't know why, but the templates for Model First (EF Designer from database) are easily customizable (but they are EDMX based), while the code for Code First from Database is not that easy - even if you manage to find the templates.
If you right click your project, click "Entity Framework" and "Customize Reverse Engineer Templates" you will get Context.tt, Entity.tt and Mapping.tt inside folder CodeTemplates\ReverseEngineerCodeFirst. However, those templates need to be called by some external caller which should pass some context information to the templates - that's why they are not ready-for-customization as the Model First templates are.
Those are the same templates that you will find in Entity Framework source code (in folder src\PowerTools\CodeTemplates\ReverseEngineerCodeFirst). And in \src\PowerTools\Handlers\ReverseEngineerCodeFirstHandler.cs you will find the method ReverseEngineerCodeFirst that reads the metadata from the database and passes to those templates. That caller method can be copied into its own T4 template (so you don't need to build that Power Tools and install in your Visual Studio), but it has some interaction with Visual Studio and with the Project, which would be hard to do with plain T4 templates.
I created a T4 template based on that method mentioned above, basically by putting together all classes/helpers that the ReverseEngineerCodeFirstHandler.cs needs, and removing references to the Visual Studio DTE. There are some instructions on my template, but basically you should remove the include for EF.Utility.CS.ttinclude, and comment out the variables "var efHost" and "var code"
Those templates that you will find in folder CodeTemplates\ReverseEngineerCodeFirst are almost identical to the Code First From Database wizard, except for some minor differences:
The wizard creates one-to-many navigation properties as HashSet<T>, while the templates creates those as List<T>
The wizard uses nullables like int? while the other uses Nullable<int>
The wizard adds some code-analysis suppression attributes [SuppressMessage]
The wizard creates the DbSets as virtual, while the templates don't.
The wizard generates part of the mappings using Data Annotations (like [Table], [Key], [StringLength], etc) and the other parts (properties and relationships) inside DbContext.OnModelCreating. The T4 templates generate all mappings inside configuration classes for each entity (EntityTypeConfiguration<Entity>).
Most of those differences can be easily adjusted, although I don't think it really matters. If you want to make strong customizations (like I did on my templates, which include automatic infer of non-existing relationships, relationships to views, class inheritance), I suggest that you create your own DTOs (or POCOs) for passing Entities/Properties/NavigationProperties to the included templates. In my case I use the original EdmMapping, map it into my DTOs, make a lot of modifications on those DTOs (based on my company standards), and pass those DTOs to the T4 includes (with small modifications).

Entity Framework 6 - reuse same table in multiple edmx files

I have been tasked with upgrading our software to use EF6. Previously it was using a combination of EF4 & 5.
We use the database first approach. The upgrade went smoothly as far a code changes go, but after running the application and doing a query the following error is thrown.
Schema specified is not valid. Errors:
The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type 'tblAccountMaintenance'.
Previously found CLR type 'DALUsers.StatusDB.tblAccountMaintenance', newly found CLR type 'DALUsers.AccountsDB.tblAccountMaintenance'.
The class in questions, tblAccountMaintenance, is generated inside multiple .tt files. The classes are references to the same table, just referenced in different .edmx files.
Simply removing one of the references is not a good option in this case as we have used a similar strategy with several other tables and would require thousands of lines of rewritten code.
What do I need to do to fix this in EF6?
So it turns out the the issue (using the same tables, with the same name in multiple edmx files in the same project) is related to the fact the the .tt files contain new objects that derive from dbContext - and this is a limitation/constraint that is specific to dbContext.
I downloaded this plugin: https://visualstudiogallery.msdn.microsoft.com/66612113-549c-4a9e-a14a-f629ceb3f89a
Which allows me to create EF6 .tt files that derive from EnityObject instead which does not have this constraint. It also makes it so I don't have to update all of my code to use the newer dbContext methods which is a plus.
As a note to others viewing this - this is probably not the best answer if you are starting with a newer project or have a small number of edmx files/tables as EntityObject is not as robust as dbContext, however this is a good band-aid fix - especially if you are like me and going to have to do a complete rewrite when EF7 comes out.

Run Add-Migration and Update-Database alike programatically

Hopefully what I'm after is possible at all. I'm currently looking at a way to do what Entity Framework Code First migrations does when you use Package Manager Console in Visual Studio but do it in runtime. The two processes I'm after are Add-Migration and Update-Database.
To explain a bit more, I want to be able to construct custom meta data for the Model and compare that against existing or non-existing database. This should output the same migration file that you get from Add-Migration command in Package Manager console.
After I've got one or more migration files I want to run the Update-Database command again in run-time, programatically to apply Up / Down changes to the database.
The key point is to be able to provide a completely custom (virtual?) model meta data to the Add-Migration procedure, not one based on actual poco classes.
If anyone has done something similar before, I'd appreciate any pointers on where to look as I didn't have much luck with Googling / EF documentation.
EDIT:
To address the WHY: I want my users to be able to define their structures in run-time. They would define the structure as part of a changeset and then be able to apply one or more changesets to the underlying database. Essentially, users would do from web-ui what a developer does from visual studio, except that the classes won't be .cs files but instead a class description in a relational database.
EF seems like a perfect fit to do this because it already does everything I need it to do. I've done schema comparison and run-time change mechanisms in the past. Since EF already does this, I don't want to reinvent the wheel. The migration files that EF Code First outputs are also a perfect fit fro what I'm trying to do.
The reason I haven't yet dug into the EF source is I wanted to check if someone else has attempted this before and if they can share and pointers. Some concrete questions:
What class / method do I need to be able to run schema compare?
How do I hook into that process to supply my own meta-data for "POCO" classes?
What are the options for outputting the detected schema changes (the Up, Down and Seed methods)? Ideally I'd like to compile a change set into a satellite assembly when user chooses to apply changes.
How can one run DbMigration instances in run-time?
I'm after some concrete examples.

Linq2Sql Buildtime takes ages

I am using Linq2Sql to access my database which is fairly large. (67 tables)
It's quite a pain in the butt to work with currently because it takes ages for the "MSLinqToSQLGenerator" to generate it's classes and finally finish compiling.
Are there any ways to speed up that process?
Like, is it possible to cache its generated output as I'm rarely touching the databasestructure?
Thank you for reading.
Moving your model to a separate assembly.
When your model is included directly in your application's project and you generate views through a pre-build event or a T4 template, view generation and validation will take place whenever the project is rebuilt, even if the model wasn't changed.
If you move the model to a separate assembly and reference it from your application's project, you can make other changes to your application without needing to rebuild the project containing the model.
Note: when moving your model to separate assemblies remember to copy the connection strings for the model into the application configuration file of the client project.
For more Information Check Performance Considerations for Entity Framework

Best way to update LINQ to SQL classes after database schema change

I'm using LINQ to SQL classes in a project where the database design is still in a bit of flux.
Is there an easy way of synchronising the classes with the schema, or do I need to manually update the classes if a table design changes?
You can use SQLMetal.exe to generate your dbml and or cs/vb file. Use a pre-build script to start it and target the directory where your datacontext project belongs.
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\x64\sqlmetal.exe
/server:<SERVER>
/database:<database>
/code:"path\Solution\DataContextProject\dbContext.cs"
/language:csharp
/namespace:<your namespace>
I haven't tried it myself, but Huagati DBML/EDMX Tools is recommended by other people.
Huagati DBML/EDMX Tools is an add-in
for Visual Studio that adds
functionality to the Linq2SQL/DBML
diagram designer in Visual Studio
2008, and to the ADO.NET Entity
Framework designer in Visual Studio
2008 SP1. The add-in adds new menu
options for updating Linq2SQL designer
diagrams with database changes, for
renaming Linq-to-SQL (DBML) and EF
(EDMX) classes and properties to use
.net naming conventions, and for
adding documentation/descriptions to
Linq-to-SQL generated classes from the
database properties.
Here is an easy fix without any additional software, that just works for simple changes (like added fields, few tables, etc).
Instructions:
You pull a copy of the changed table into the designer (will be removed later)
Now select all the new (or changed) fields and (right-click ->) copy
In your original table right click and insert them (delete changed fields first)
Now delete the table you copied them from
I know it is kinda obvious, but somehow non-intuitive, and it helped me a lot, since all the right attributes and types will be copied, and all links stay intact. Hope it helps.
When to use:
Of course it is - as said - for small changes, but surely better than manually replacing tables with many links, or when you don't want your whole database structure generated by SQLMetal. For example when you have a big amount of tables (e.g. SAP), or when using cross-linked tables from different databases.
DamienG has written some t4 templates which can replace some of what VS generates for you. These can be rerun whenever you like via a command line tool.
T4 templates have the added benefit of being editable. This allows you to tweak what is generated to you hearts content.
I think Jeff complained about this recently. One common technique is to drag all the objects into the designer again...
I hope someone else chimes in with a better approach!
I wrote a tool to do script changes to Dbml scripts see http://code.google.com/p/linqtodbmlrunner/ and my blog http://www.adverseconditionals.com
How about modifying the Properties of the entity/table within the DataContext design surface within Visual Studio?
For instance if I added a column to an SQL Server table:
Open the *.dbml file.
Right click the entity and select Add > Property.
Fill out the values in the Properties window for the new column.
Build your solution.
The auto generated model classes should reflect the new column that was added.

Categories