I have one website that uses EF 4.4 (.NET 4.0 version of EF 5.0) that uses Code First against an existing database. I use the Devart oracle data provider which requires a workaround because of casing issues with the model type.
It makes the Devart provider recognize lowercase datatypes to interpret the schema. (Or something along those lines)
This works properly, until the control within this website, built on EF 4.1 Database First (Also against an existing database) tries to load. The Devart provider seems to be shared across the websites, and it results in errors about the provider not being able to recognize the datatypes (correctly) in all caps, because of the previous workaround to make it work in Code First.
Is there a workaround for this, or do I have to convert the Database First approach to Code First?
Edit: Here is the related workaround code. I seem to have lost the forum post I got it from. I believe it was on the Devart forums:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var config = Devart.Data.Oracle.Entity.Configuration.OracleEntityProviderConfig.Instance;
config.Workarounds.ColumnTypeCasingConventionCompatibility = true;
... initialization code here ...
base.OnModelCreating(modelBuilder);
}
And the related error is this:
System.Data.MetadataException: Schema specified is not valid. Errors:
Model.ssdl(205,6) : error 0040: The Type CHAR is not qualified with a namespace or alias. Only primitive types can be used without qualification.
Model.ssdl(206,6) : error 0040: The Type VARCHAR2 is not qualified with a namespace or alias. Only primitive types can be used without qualification.
There are a bunch more, but they're all the same error with different lines and data types.
The Devart provider seems to be shared across the websites
After the ColumnTypeCasingConventionCompatibility option is set, it determines the behaviour of the current application domain (web site). The process (web server) may run several application domains with different values of ColumnTypeCasingConventionCompatibility.
The value of ColumnTypeCasingConventionCompatibility for the particular application domain depends on the Fluent Mapping property of the DbContext template used for the model in web site. Fluent Mapping=true must be used with ColumnTypeCasingConventionCompatibility=true, and vice versa: Fluent Mapping=false must be used with ColumnTypeCasingConventionCompatibility=false.
You can set ColumnTypeCasingConventionCompatibility for a web site in the following alternative ways:
a) in your code before the first usage of the context (e.g., in a static constructor of the context or in the Main method of your program, etc)
b) in *.config. For example:
<configuration>
<configSections>
<section name="Devart.Data.Oracle.Entity"
type="Devart.Data.Oracle.Entity.Configuration.OracleEntityProviderConfigurationSection,
Devart.Data.Oracle.Entity, Version=7.5.179.0, Culture=neutral,
PublicKeyToken=09af7300eec23701" />
</configSections>
<Devart.Data.Oracle.Entity xmlns="http://devart.com/schemas/Devart.Data.Oracle.Entity/1.0">
<CodeFirstOptions ColumnTypeCasingConventionCompatibility="true"/>
</Devart.Data.Oracle.Entity>
</configuration>
Related
When use EF with breezejs, seems server side should have each name starts with upper case, and on client side, use camel style, like
FirstName on EF and
firstName on client side.
I think it is not as good as all lower case, everyone can understand firstname, not necessary FirstName or firstName.
I wonder if it is strongly suggested to not use all lower case name? If I want to use all lower case name, is there a way to tell EF (database first) to create class with all lower case name no matter what they are on the db side?
Thanks
I think you should do this within your JSON serialization and deserialization. If you're using Web API you can do this. From OdeToCode:
var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
If you don't want to do this with your JSON serialization, then if you're using EF6 code first you can do some custom conventions to achieve this for your column names. Do something similar for tables.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder
.Properties()
.Configure(p => p.HasColumnName(p.ClrPropertyInfo.Name.ToLower()));
modelBuilder.Configurations.Add(new UserConfiguration());
modelBuilder.Configurations.Add(new UserHashHistoryConfiguration());
}
See this post on MSDN for more information on custom conventions in EF6.
This is what the Breeze NamingConvention is for.
See: http://www.breezejs.com/documentation/naming-convention
But you may have a problem because the NamingConvention needs to be able to roundtrip your name. i.e. passing from server name to client name and back to server name needs to get back to the original name. With your rule there is no way to get from an all lowercase name back to the original server name unless you are willing to keep a map of all previously mapped names or come up with some other heuristic.
The example below demonstrates the issue.
var lowerCaseNamingConvention = new breeze.NamingConvention({
serverPropertyNameToClient: function (serverPropertyName, prop) {
return serverPropertyName.toLowerCase();
}
clientPropertyNameToServer: function (clientPropertyName, prop) {
// need to get back to original name here
return clientPropertyName. ???
}
});
lowerCaseNamingConvention.setAsDefault();
I'm not clear on why you want to change the property names on the server-side. Property names in .NET classes are expected to be PascalCase.
You're free to do as you please and name the properties as you wish in the EF mapper. It's harder to do in EF Database First; you can use the designer to map each property name exactly as you want to see it but wow is that time consuming. There are advanced techniques with T4 that might be better if your model is huge (beware: you can spend more time writing/debuggin T4 than just slogging through and mapping the property names by hand).
If you were willing to go with Code First, you could take a look at EF 6 custom conventions which appear to be sufficiently flexible and powerful.
You DO realize that this is not a breeze question, right? The Breeze NamingConvention (mentioned by others) is the proper place to make your client-side properties look the way you want them to look.
There isn't always a way to calculate the transform; sometimes you just have to provide a dictionary in your NamingConvention.
However, you seem to want to handle this by remaking the classes on the server. That (as you've noted) is harder and/or tedious. There is nothing Breeze can do about that.
p.s.: using JSON.NET configuration to try to cope with this during serialization will not work. You want property names that you can reference in queries and JSON.NET does nothing to morph the property names mentioned in query strings.
I am having trouble finding faked Thread.Sleep in mscorlib.fakes library.
I am following direction at http://www.codewrecks.com/blog/index.php/2012/04/27/using-shims-in-visual-studio-11-to-test-untestable-code/
http://msdn.microsoft.com/en-us/library/d00bd51t(v=vs.100).aspx shows Thread.Sleep is in mscorlib so I added its fake but System.Threading.Fakes namespace doesn't contain ShimThread nor StubThread.
Thread is a sealed class but VS fake framework should be able to fake static method in sealed class.
This is very much possible. By default Fakes framework doesn't generate shims for most types (including types in System.Threading namespace) of mscorlib because Fakes framework itself makes use of mscorlib. So only a few of the types are shimmed,
However, you can configure this behavior by changing the mscorlib.fakes file added in your project.
<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
<Assembly Name="mscorlib" Version="4.0.0.0"/>
<ShimGeneration>
<Add Namespace="System.Threading!"/>
</ShimGeneration>
</Fakes>
Now build the test project and you can see shims for types in the System.Threading namespace, including ShimThread.SleepInt32.
Read more about the .fakes xml file on this page
This is because the Shim framework cannot fake all .Net BCL classes in mscrolib and System, see: MSDN.
Unfortunately I couldn't find a list of types that aren't supported. But it seems, primarily types that are not pure CLR classes or need OS functionality (Thread, FileSystemWatcher, ...) are not supported at this time.
As my database was designed using german table- and column names, the default pluralisation feature of entity framework doesn't work for me.
I have found a couple of resources where this is discussed, but none of them seem to work.
What i have found:
There is the PluralisationService where i can add the mappings:
PluralizationService pluralizer =
PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-us"));
ICustomPluralizationMapping mapping = ps as ICustomPluralizationMapping;
mapping.AddWord("Tabelle", "Tabellen");
But what's next?
I have tried to:
EntityModelSchemaGenerator generator = new EntityModelSchemaGenerator(container);
generator.PluralizationService = pluralizer;
generator.GenerateMetadata();
and put both of them in my POCO T4 Template. But it throwed the following exception:
The EntityContainer 'ContainerName' is not a store EntityContainer. Parameter name: storeEntityContainer
at System.Data.Entity.Design.EntityModelSchemaGenerator.Initialize(...)
at Microsoft.VisualStudio.TextTemplating...GeneratedTextTransformation.TransformText()
To completely customize the table names in EF Code First, you can use the Table attribute to explicitly specify the name of the table associated with a class:
[Table("InternalBlogs")]
public class Blog
{
//...
}
I'm also looking for the same thing. Maybe this can help. I'm just not willing to pay for such a basic feature.
EDIT:
The code you posted is to be used with EdmGen2 wich will give you CSDL, SSDL or MSL files pluralized according to your class.
A very old question, but if someone is still looking for a possible workflow/solution:
I had a similar problem where I wanted to customize the schema import (CSDL) from the database. The solution / workflow was as follows:
Deployed the database schema (I used Visual Studio Database Project VS 201x) to a
local database
Imported the database model using EDMGEN to create the CSDL, SSDL and MSDL files
http://msdn.microsoft.com/en-us/library/vstudio/bb387165(v=vs.110).aspx
Modified EDMGEN2 with my changes on how to handle pluralization and naming with custom rules and created EDMX file
Ran the T4 templates (with additional customization as needed) to create
output.
I have DAL (model first entity framework 4.1) and Service which is using it in separate projects. Everything was working fine, but after some minor changes (for example I generated model from database) it stoppedd working. I am now getting metadata exception.
After many hours of research I downloaded ILSpy and checked that inside DAL.dll there are no resources.
My connection string looks like:
metadata=res://*/DataModel.TerminalRegistryModel.csdl|
res://*/DataModel.TerminalRegistryModel.ssdl|
res://*/DataModel.TerminalRegistryModel.msl;
ANd in EDMX file metadata artifact processing is set to Embed in Output Assembly.
What can cause my problem?
The standard metadata string looks like this:
metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl
And this works fine in most cases. However, in some Entity Framework get confused and does not know which dll to look in. Therefore, change the metadata string to:
metadata=res://nameOfDll/Model.csdl|res://nameOfDll/Model.ssdl|res://nameOfDll/Model.msl
I have two projects:
ASP.Net 3.5 website (frontend, UI)
VB Class Library (dataaccess logic)
Where should I save my connectionString, so that I can use if from the class library? And how does this affect where it is placed when I deploy/publish?
Note:
I don't want to pass it to every function in my VB Class
Depending on how you constructed your DAL -- LINQ, TableAdapters, etc. -- it may automatically look for it in the web.config file. If you created the DAL via a designer, likely it stores the default connection string in the app.config file for you class library. I copy the connection strings section from the app.config file to my web.config and change the connection string to the correct database (I have separate web.config's for DEV/QA/PROD). This makes it trivial since the designer generated code already has the code implemented to retrieve it from the configuration file.
If you are hand-coding your DAL and need to pass in the connection string, I suggest setting up a strongly-typed configuration class that interfaces to the web.config and does lazy loading of your configuration values. Use a factory to create your DAL and inject the configuration class into your factory via constructor so that it knows how to create your DAL with the connectionsString retrieved from the configuration file.
My question came from having spent half a day of trying to make this work, but I kept getting the wrong connection when deploying (where I use another database).
My problem was, that I was using
My.Settings.DefaultConnectionString
...To retrieve the connectionString in my VB Class Library.
After following tvanfossons anwer, I dug around some more and found out, that I can simply use (after referencing system.configuration) :
System.Configuration.ConfigurationManager.ConnectionStrings.Item("DefaultConnectionString").ConnectionString
It looks in the web-config for webapplications and app.config for windows/class library apps.
I am glad it now works, but even more glad I know why. ;)
I had the same issue you were having and I ended up using the System.Configuration.ConfigurationManager class to obtain the connection string stored in my web.config file from my class library like Kjensen's answer suggested. This worked wonders, if I had more experience I would vote that answer up.
I needed the connection string to build my Linq2Sql data context, which this method provided me with.
I now build my data context like below (remembering to add a reference to System.Configuration) -
public MyDataContext() : base(System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"]
.ConnectionString, mappingSource)
And as long as the web.config file contains "MyConnectionString" the configuration manager takes care of the rest.
We keep ours in the machine.config of each server and have a custom DAL to handle all DB interaction for our web apps.
Put it in the web.config in the connection strings section.
In the VB project use HttpContext.Current.GetSection to retrieve the section.
A fellow developers idea once was that we should store all the connection strings in a database table.
Don't try doing that. You won't get very far. :)