EntityFramework: how to modify edmx to change format of entity names and properties - entity-framework

I am using the Entity Framework to generate data access code from an old database.
The database table names and properties are all named in capitals with _ to separate words ie. CLIENT, CLIENT_NAME, D_CLIENT_ID etc.
I have written a class to transform these into camel cased strings:
public static class Extensions{
public static string FirstCharToUpper(this string input)
{
return input.First().ToString().ToUpper() + input.Substring(1).ToLower();
}
public static string CamelCase(this string input)
{
return input.Split('_').Where(a=>!string.IsNullOrEmpty(a)).Select(a=>a.FirstCharToUpper()).Aggregate((a,b)=>a+b);
}
}
I am invoking this from my tt files and I have got to the point where my data classes and DbContext naming is the way I want it.
However I now get an error when I try to create a controller: 'Unable to retrieve metadata for myNamespace.Client'. Could not find the CLR type for 'myModel.ENTITYNAME'. (in capital)
To fix this, I made my Data.tt decorate my data classes with [Table("ENTITYNAME")] and my properties with [Column("COLUMNNAME")] - however this did not make any difference.
What am I missing?

Are you updating it the same way in all three (or two corresponding) layers: CSDL/MSL/SSDL? I would suspect there is a mismatch between two of the layers.
Possible useful in this case - here is a library I wrote for creating/updating/manipulating EDMX files a bunch of years ago: https://github.com/KristoferA/HuagatiEDMXTools/
If you use an older version of Visual Studio (2013 or older) then I also have a free VS addon/plugin that adds renaming and db<->model sync etc. You can download it from here:
https://huagati.com/edmxtools/
Update: based on the comments below, I think you are renaming classes and properties in the generated code without making the corresponding change in the CSDL.
Instead of changing the generated code / tt templates: change the names in the CSDL and the references to those CSDL objects in the MSL. Then the default templates will generate code with the class/property/etc names you want.

Related

Entity Framework generated classes are not in the namespace I require, is there a way of changing the namespace it uses without regenerating?

If I need to regenerate where should the namespace be specified. I am trying to use partial classes from within the Models namespace however they don't match.
The simplified code fragment below is where the entity framework classes have been generated
namespace projectname
{
#region Contexts
/// <summary>
/// No Metadata Documentation available.
/// </summary>
public partial class MyClass
{
}
}
When I add a class to my models folder,
namespace projectname.Models
{
public partial class MyClass
{
//etc, etc
}
}
As you can see the namespaces don't match causing issues when I try and use them as the compiler is seeing both projectname.Models.MyClass and projectname.MyClass.
I would like some advice on the correct way to fix this, preferably to update the E.F. classes so they exist in the projectname.Models namespace, but I am not sure how to go about it.
In line with Roman O's comment, namespace can be changed by updating "Custom Tool Namespace" property of text transform (.tt) file, which ties generated entity classes (in Database First approach) to entity model (.edmx) file. This works in VS 2012 Express with EF 5.0.
I would post a screenshot but for lack of reputation.
IIRC, if you are using an Entity data model, you should be able to change the namespace directly through the xml file or files (you may have to change it for all the various storage and and conceptual models). There might even be some way to change it in the designer.. seems simple enough.
Actually, the solution might be here:
Generated Code Overview (Entity Data Model Designer) (see Custom Tool Namespace)
Right click the .edmx file in the project in Solution Explorer and select Properties
In the VS properties pane, fine Custom Tool Namespace
Enter the full CLR namespace you'd like
Rebuild the project
Namespace of auto-generated classes will be inherited from VS project settings (and even change if you change it there). Of course you should have "Custom Tool Namespace" property empty. (just tested it with VS2013 and EF6.1)
Unlike settings files which had always been pita :)
For older version there is a good video on manual changing :
https://youtu.be/B7Cqc9F0Ih8

Drools Guvnor data enumeration API

In Guvnor documentation, I know how to define data enumeration and use it in Guvnor. Is it possible to fetch data enumeration from my own Java code?
From Guvnor's documentation:
Loading enums programmatically: In some cases, people may want to load their enumeration data entirely from external data source (such as a relational database). To do this, you can implement a class that returns a Map. The key of the map is a string (which is the Fact.field name as shown above), and the value is a java.util.List of Strings.
public class SampleDataSource2 {
public Map<String>, List<String> loadData() {
Map data = new HashMap();
List d = new ArrayList();
d.add("value1");
d.add("value2");
data.put("Fact.field", d);
return data;
}
}
And in the enumeration in the BRMS, you put:
=(new SampleDataSource2()).loadData()
The "=" tells it to load the data by executing your code.
Best Regards,
I hope its not too late to answer this.
To load enum from application to guvnor,
Build the enum class dynamically from string (in my case enum values is provided by user via GUI)
Add it to a jar, convert it to byte array
POST it to guvnor as asset (model jar) via REST call
Call save repository operation (change in source code of guvnor)
Now enum will be visible as fact in your rule window.
Editing/Deletion of model jar and validation of rules aftermath is something you have to take care.

Entity Framework 5 model first - Where is IDisposable gone?

In Entity Framework 5 model first, there seem to be some breaking changes due to the way the class files are generated (No more code generation, but T4 templates)
2 examples:
The generated context file doesn't implement IDisposable anymore
There isn't a constructor which takes a connectionstring anymore
Are there more breaking changes? And what is the solution to them?
The default code generated from a model in Entity Framework 5 now inherits DbContext instead of ObjectContext.
This still implements IDisposable, but if you're getting an error from a line of code similar to this:
using (var mymodel = new MyModelContext()) { ... }
...complaining about not implementing IDisposable, then your problem is most likely that your model is defined in a separate assembly that references EF5 and you have not added an EF5 reference to your project.
As Ladislav Mrnka has already mentioned in his answer, if you want to pass a connection string to the constructor you have to create your own constructor manually to do this.
If you want to switch Entity Framework back to the older style of generated code, which will automatically generate the constructor you're looking for, then follow these steps:
Click on the designer surface of your EDMX file, and look at the properties window. Find a property called "Code Generation Strategy" and set this to "Default" instead of "None". This will tell Visual Studio to start creating the code for your object model in MyModel.Designer.cs in one big file, this time using ObjectContext instead of DbContext.
Delete the following sub files from below your EDMX file: MyModel.Context.tt, MyModel.tt. These are the auto generated files that you don't want anymore. If you don't delete them you'll get class naming conflicts because your objects will be created twice.
The generated context file doesn't implement IDisposable anymore
IDisposable is still implemented by the parent context type. The generated type is still disposable.
There isn't a constructor which takes a connectionstring anymore
It now uses convention to get connection string but you can add your own constructor either to template or to your partial class part of the context.
Are there more breaking changes? And what is the solution to them?
It is whole breaking change because it uses different API - DbContext API instead of ObjectContext API which means different types, different methods, POCO entities etc. If you want to get back to original code generation you have to delete those T4 templates and enable code generation as described in .Designer.cs file but the current recommended way is to use POCOs and DbContext API.
I was having the same issue with the using statement needing a type that extended IDisposable... Turns out that I forgot to reference System.Data.Entity in my project... Added the reference and it fixed the problem.
Just clean and build the project, don't forget to add the reference to your entity.

How do I pass a connection string to the constructor of a database-first DBContext with Entity Framework 4.1?

For various reasons I would like to not store the connection string for my Entity Framework DB model in one of the various .config files. (I am using the latest and greatest DBContext API with the new Entity Framework version 4.1, .NET 4 and Visual Studio 2010 C#.) However, the code generation template for DBContext only creates a single parameterless constructor. (If I don't use the DBContext API, then my entity framework model has 7 different constructors to chose from, including the one I want.)
The only way I could figure out how to do this was to directly modify the code-generation template (context.tt file) to give me the constructor I want (example code below). This works, but it feels like I'm doing it "the hard way". What is the correct way to get a DBContext constructor that accepts a connection string?
public <#=Code.Escape(container)#>(string connectionString)
: base(connectionString)
{
<#
WriteLazyLoadingEnabled(container);
#>
}
One final note in case it might help somebody else. Although this method works, it took me a while to realize that the "connection string" is not strictly the DB connection string, but rather the special entity framework connection string which contains the DB connection string (just like what would be stored in the app.config file).
Your approach looks like the most correct way to do this. It's what the t4 templates were created for, and you're basically doing the same thing that the model-first templates do by default.
Another possibility would be to make the db context class be partial (if it isn't by default) and create another partial class file alongside it to add the constructor you want. But it seems likely that you'll want all of your t4-generated contexts to follow this pattern, so I think it's best to leverage the code generation to do this automatically the way you do in the question.

Unicode table name problem with DbContext in Entity Framework 4.1

I thought I'd try the new DbContext way of doing things in EF 4.1, but ran into a problem.
I generate a new entity data model from database (SQL Server 2008) and then I use the DbContext generator.
When I try to fetch the table called Länder i get an exception.
var db = new MyEntities(); // instantiate DbContext subclass
var countries = db.Länder.ToList(); // boom
EntitySqlException: The simple identifier 'Länder' must contain basic Latin characters only. To use UNICODE characters, use an escaped identifier.
If if try other tables with latin names - all is fine. And I don't have this problem when using ObjectContext.
How am I supposed to escape the table name?
We (the EF team) investigated and found that we were not properly escaping (i.e. adding square brackets) for the names of the entity sets when we bootstrap the DbSets.
Thanks a lot for reporting this!
We are currently testing a fix that should be included in a future release. In the meanwhile, you should be able to workaround this by specifying the entity set name explicitly such that it doesn’t contain any characters that would need escaping.
When using Database First or Model First this can be done by editing the entity set names in the designer. When using Code First, it can be done by changing the name of the DbSet property:
public DbSet<Länder> Lander { get; set; }
or by overriding OnModelCreating in the context:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Länder>().HasEntitySetName("Lander");
}
It looks like a bug in DbContext API because internally the query is converted to entity SQL which is parsed and if identifier contains national / unicode characters it must be escaped [Länder] but it is not. That is something you probably cannot control from your code.
I'm strongly against using non English names for identifiers (both code and database) so this is just another reason why it prove to be a wrong idea.
This bug is fixed in 4.3
http://blogs.msdn.com/b/adonet/archive/2012/01/12/ef-4-3-beta-1-released.aspx