When working in Ruby (specifically, in Rails), I can automatically run my tests using a testing database, and also choose easily between a development or production database. Still new to Entity Framework (WPF), but it seems less than simple.
My Entity assembly has an App.Config file that holds a reference to the database, and I need to copy this App.Config file to all runnable projects (e.g. questions 1113361 and 2233897).
If I use Test->Database Test Configuration without explicitly copying App.Config from my EF project, I get
System.ArgumentException: The
specified named connection is either
not found in the configuration, not
intended to be used with the
EntityClient provider, or not valid.
which is the same as if I have a missing or different App.Config file.
Strangely even if I do change all the connection stings in my Entity project and testing project to the same database, I still get that error.
Is there a step I'm missing when telling Visual Studio (2010 Ultimate) that I want my tests to run using a different testing database, or is this just not supported with EF 4?
Also, Is there some way to change database context other than copying App.Config files back and forth? Seems like a serious way to ignore separation of concerns if not, so I think I'm missing something.
Strangely, as I was playing around after doing this, it started working. Somebody might comment on this, but it looks like I was using Test->Database Test Configuration at the wrong time.
To wit:
Clean project, no App.Config, use Test->Database Test Configuration to set the test database. It generates an app.config (lowercase, notably). You get an error. Even if you check all the connection strings (weird)
Clean project, first copy the App.Config from from you Entity project. Now when you use Test->Database Test Configuration, it will populate the App.Config that you copied, and it works.
I imagine it was some issue I was creating when copying the connection strings.
I've also confirmed that this works with my Entity project using a "Main" database while my testing project uses a "Test" database.
Wonder if someone can confirm/clarify this?
Related
I've hit a wall when it comes to how the Universal Windows Platform connects/manages/interacts with a local SQL Server database. My current project (WPF using .NET Framework 4.8) that I'm interested in porting over to UWP uses EntityFramework 6 with ADO.NET models and it works like a charm. No issues at all. UWP on the other hand, well I'll just say that I have absolutely no idea what's going on when it comes to connecting to a local instance of SQL Server. I've gone through about 3-4 different guides/templates and none have worked. I really want to use UWP and take advantage of all the new features coming for Windows 10 v2004, but it doesn't look like this will happen.
As I currently understand the process, I need to essentially create two separate projects within the same solution. One is the UWP main program and the other would be a .NET Core class library that targets the .NET Standard 2.0 platform. I also have read that EntityFramework 6 is not supported on .NET Core or UWP, so the only way is by using EntityFrameworkCore (more specifically NuGet package Microsoft.EntityFrameworkCore.SqlServer). So I installed it on the .NET Core class library and then set a reference from the UWP app to the class library. Because the local SQL Server is already up and running, I'm not doing what is called the 'code first' approach to the creation of all the models/DbContext.cs files. Based on what I've read, the ONLY way to import a currently existing SQL Server into the data model is by use of the Scaffold-DbContext command with a standard connection string through the package manager. Surprisingly, this worked on the first attempt and the models and DbContext were all created without any issues.
This is about as far as I seem to be able to get as everything after does nothing but throw exceptions. If I try to pass any C# code using the DbContext to retrieve any data from the database, I get about 10-15 exceptions that essentially say the program can't find or connect to the database. I have manually edited the connection string in every way imaginable, but nothing seems to work. I also tried to manually set up a new connection using Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient.SqlConnectionStringBuilder and System.Data.SqlClient.SqlConnection but they all fail with the same exceptions.
Sorry for the long post but at this point, I really don't know what's going on and would really appreciate any feedback you all could offer.
Update 1
So, I went back through my currently working app on .NET Framework and looked for the connection string in the App.config file to see what the regular EntityFramework is using and it's completely different than anything I've used before. My guess is that it's generating a completely custom connection string that includes references to all sorts of files and a property called 'ProviderName'. Will try cutting and pasting this string into UWP to see if it'll work.
Update 2
I think I'm missing something fundamental on this. I can generate the scaffold with a connection string without any issues, but if I attempt to open a connection at runtime using the same connection string, I'm getting errors.
Finally was able to get a connection at runtime after months of trial and error. Without getting into too much detail, here's what worked for me (assuming EFCore has already generated a DbContext file):
Enable Enterprise Authentication.
Enable TCP/IP connections to the SQL Server instance.
In Visual Studio's server explorer, click Add Connection. If you already have a connection saved for the database, right click the server and click Modify Connection
In the connection properties window, click the Advanced button. Make a note of all of the listed parameters and their values and save it.
Open the data context file that isn't able to connect and add a using statement for Microsoft.Data.SqlClient. Now locate the OnConfiguring method. Use a SqlConnectionStringBuilder and configure all of the parameters from the advanced connection properties that were saved earlier.
And that should work. If there are still errors, I would double check the parameters to make sure they were all entered correctly.
Hope this post will help out anyone else dealing with this issue.
Let's say that I have a simple WPF or Winforms solution. To that solution I add a new project (based on a class library template , which I then reference in the main project) which is intended to be a data layer containing an entity framework data model. When I create the data model in the new project the connection string that it uses gets added to the app.config file of the main project in the solution.
Now let us say that I want to add two more projects to the solution (both of which will again be based on class libraries) to contain details of WCF services that I wish to use. In each case I add the WCF service by using the ADD Service Reference option from the right click context menu of the projects.
Unlike the data model project though the bindings for the service model get added to the local projects app.config file ass opposed to the app.config file of the main start-up project.
Should I simply copy those bindings to the start-up project's app.config file, or should I copy and then delete, or in fact should I be doing something completely different. Thus far trying combination of the first two suggestions I get error messages connected with endpoint configuration, however my knowledge of WCF is not really sufficiently good to fully understand the MSDN articles that the error list points me to.
Note that if the service references are added to the main project I get no errors whatsoever, so I figure this must be a configuration problem of some description.
Would anyone be able to provide the correct procedure for adding projects that essentially contain no more than a WCF service reference to an existing visual studio solution.
Edit
The screenshot below shows my main app.cofig file after having copied over the bindings configurations from the two service contracts. I'm not sure whether I should have commented out the bit that I did or not, I had thought that by doing so I might get rid of the blue squiggly underlines telling me the following (which I must admit to not understanding):
Warning The 'contract' attribute is invalid - The value 'ErsLiveService.IERSAPIService' is invalid according to its datatype 'clientContractType' - The Enumeration constraint failed.
You're likely getting the blue squigglies because the namespace ErsTestService is defined within the project in which you created the service reference. If the root namespace of that project is MyServiceReferenceProject then try changing the namespace to MyServiceReferenceProject.ErsTestService.IERSAPIService.
I hope someone have already faced an issue to verify that application shows correct data from database. I reviewd how groovy used SQL, but I have no idea where and how I should do that. I'm just starting to use gradle+Spock+Geb for testing application. I have a few files where I described a couple of pages from application, a couple of modules and a file with spock specification. Where and how I need to connect to Oracle DB, use SQL and compare result's data with application's ones?
P.S. I write everything in notepad++ and launch from command line writing 'gradlew firefoxTest'. Does exist any more comfortable way to work with gradle+spock+geb?
Thanks in advance.
Because there are no other answers, I wanted to provide a solution someone at my company thought of. This assumes you already have a project that uses some sort of JDBC. In our case it is JDBI.
The idea is to extend Classloader and then use that to directly access the data access object class via the JVM. That idea should work.
I have not tested it out because it doesn't completely fit our use-case. I'll admit that this does not completely apply to your use case, but technically you could just run the jar of an existing project, which can access the database.
OK, so I did the dumb thing and released production code (C#, VS2010) that targeted our development database (SQL Server 2008 R2). Luckily we are not using the production database yet so I didn't have the pain of trying to recover and synchronize everything...
But, I want to prevent this from happening again when it could be much more painful. My idea is to add a table I can query at startup and determine what database I am connected to by the value returned. Production would return "PROD" and dev and test would return other values, for example.
If it makes any difference, the application talks to a WCF service to access the database so I have endpoints in the config file, not actual connection strings.
Does this make sense? How have others addressed this problem?
Thanks,
Dave
The easiest way to solve this is to not have access to production accounts. Those are stored in the Machine.config file for our .net applications. In non-.net applications this is easily duplicated, by having a config file in a common location, or (dare I say) a registry entry which holds the account information.
Most of our servers are accessed through aliases too, so no one really needs to change the connection string from environment to environment. Just grab the user from the config and the server alias in the hosts file points you to the correct server. This also removes the headache from us having to update all our config files when we switch db instances (change hardware etc.)
So even with the click once deployment and the end points. You can publish the a new endpoint URI in a machine config on the end users desktop (I'm assuming this is an internal application), and then reference that in the code.
If you absolutely can't do this, as this might be a lot of work (last place I worked had 2000 call center people, so this push was a lot more difficult, but still possible). You can always have an automated build server setup which modifies the app.config file for you as a last step of building the application for you. You then ALWAYS publish the compiled code from the automated build server. Never have the change in the app.config for something like this be a manual step in the developer's process. This will always lead to problems at some point.
Now if none of this works, your final option (done this one too), which I hated, but it worked is to look up the value off of a mapped drive. Essentially, everyone in the company has a mapped drive to say R:. This is where you have your production configuration files etc. The prod account people map to one drive location with the production values, and the devs etc. map to another with the development values. I hate this option compared to the others, but it works, and it can save you in a pinch with others become tedious and difficult (due to say office politics, setting up a build server etc.).
I'm assuming your production server has a different name than your development server, so you could simply SELECT ##SERVERNAME AS ServerName.
Not sure if this answer helps you in a assumed .net environment, but within a *nix/PHP environment, this is how I handle the same situation.
OK, so I did the dumb thing and released production code
There are a times where some app behavior is environment dependent, as you eluded to. In order to provide this ability to check between development and production environments I added the following line to global /etc/profile/profile.d/custom.sh config (CentOS):
SERVICE_ENV=dev
And in code I have a wrapper method which will grab an environment variable based on name and localize it's value making it accessible to my application code. Below is a snippet demonstrating how to check the current environment and react accordingly (in PHP):
public function __call($method, $params)
{
// Reduce chatter on production envs
// Only display debug messages if override told us to
if (($method === 'debug') &&
(CoreLib_Api_Environment_Package::getValue(CoreLib_Api_Environment::VAR_LABEL_SERVICE) === CoreLib_Api_Environment::PROD) &&
(!in_array(CoreLib_Api_Log::DEBUG_ON_PROD_OVERRIDE, $params))) {
return;
}
}
Remember, you don't want to pepper your application logic with environment checks, save for a few extreme use cases as demonstrated with snippet. Rather you should be controlling access to your production databases using DNS. For example, within your development environment the following db hostname mydatabase-db would resolve to a local server instead of your actual production server. And when you push your code to the production environment, your DNS will correctly resolve the hostname, so your code should "just work" without any environment checks.
After hours of wading through textbooks and tutorials on MSBuild and app.config manipulation, I stumbled across something called SlowCheetah - XML Transforms http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5 that did what I needed it to do in less than hour after first stumbling across it. Definitely recommended! From the article:
This package enables you to transform your app.config or any other XML file based on the build configuration. It also adds additional tooling to help you create XML transforms.
This package is created by Sayed Ibrahim Hashimi, Chuck England and Bill Heibert, the same Hashimi who authored THE book on MSBuild. If you're looking for a simple ubiquitous way to transform your app.config, web.config or any other XML fie based on the build configuration, look no further -- this VS package will do the job.
Yeah I know I answered my own question but I already gave points to the answer that eventually pointed me to the real answer. Now I need to go back and edit the question based on my new understanding of the problem...
Dave
I' assuming yout production serveur has a different ip address. You can simply use
SELECT CONNECTIONPROPERTY('local_net_address') AS local_net_address
We are starting a new WinForms project and decided to use TeamCity to create builds and run unit and integration tests. The project deals with database. We have 3 databases (developDB (this is used by developers while developing =) ), testDB (this is used by teamcity to run tests) and productionDB(this is used by client)). TeamCity has 3 buildConfiguration. The first is triggered when commit happens. The second is triggered every night to run integration tests. And the third is triggered by developer when we what to make a release. So I want TeamCity to be able to change connectionString depending on what kind of build happens. Also I don't want to store connectionString in app.config (I don't want client to know the user and password). What options are available to perform the task?
Thanks in advance!
Updated
I use NHibernate and FluentNHibernate to connect to databases if it matters.
In this situation, I would use TeamCity to run a nant script to perform the build.
NAnt allows you to modify config file values (such as your connection string) at build time.
An example of using TeamCity/NAnt to deploy to different staging environments can be found at this blog post:
http://thecodedecanter.wordpress.com/2010/03/25/one-click-website-deployment-using-teamcity-nant-git-and-powershell/
As #surfen suggests, the connection string values for each environment should be encrypted to prevent credentials from being stored in plain text.
I have not used TeamCity, but I have written multiple applications with dynamically changing ConnectionStrings during logon process (ie. at runtime), and It's quite simple.
You didn't tell how do you connect to your Database. Since you mention app.config, I suppose it is ADO.NET DataSets or simmilar technology, which creates a read-only(getter) ConnectionString in your Settings.Designer.cs / app.config.
What I did, was to create a setter method in Settings.cs (not Settings.Designer.cs) for the ConnectionString property like this:
public void setNorthwindConnectionString(String value) {
this["NorthwindConnectionString"] = value;
}
My generated DataSet then uses this NorthwindConnectionString for accessing data.
You can use preprocessor directives for conditional setup of your ConnectionString:
#if DEBUG
Console.WriteLine("Mode=Debug");
Settings.Default.setNorthwindConnectionString("(DebugDBConnectionString)");
#else
Console.WriteLine("Mode=Release");
Settings.Default.setNorthwindConnectionString("(ReleaseDBConnectionString)");
#endif
You could also encrypt your connection strings, and copy the right app.config during post build event.
I am assuming you would be using msbuild to build your projects in Team city. If that is the case, then you can send the Conditional Compilation Symbol where in you can pass what ever symbols you need.
Once you have the symols, you can do things like:
#if DEVBUILD
//.... Your Connection String Code here
#endif
#if INTBUILD
.... Your Connection String Code here
#endif
That's the answer to your frst question.
Looking at the second part of your question, where in you do not want to store the user name & password in the app.config,
Options:
try intergrated security, it will use your domain account
if option cannot be used, try keeping your connection string as a Registry Key, so that its not obvious or an Environment variable.