I have developed a MVVM application using Visual Studio 2010, Entity Framework and Oracle Data Access v. 126.96.36.199. Development computer uses a Oracle Client 10.2.0 and TNSNAMES.ORA to connect to Database. Then I deployed my app to a web server, to share it with the users
Everything is Ok, until I try to run the deployed app from a "clean" user computer (i.e. no Oracle Client and tnsnames.ora installed). Of course, app is unable to reach database!
I read a lot of articles suggesting to use Oracle Instant Client 188.8.131.52 and Odac11 Xcopy, and copy some DLL's into project root. I also tried to replace Oracle Data Access with Oracle Data Provider for .Net Managed Driver, release 184.108.40.206 (for 64-bit development computer). Really, I got to make my app work using a "local" tnsnames.ora (put in the project folder), and then bypassing my oracle client. but every attempt of running the deployed app was unsuccessful. App keeps looking for a tnsnames.ora in the client computer.
How can I fix this issue? I guess I should be able to package some oracle driver, and maybe a minimal tnsname.ora into my deployment, but I dont know how to do it. Please help
If the requirement is not to have an Oracle Client, then you must use managed ODP.NET. All forms of unmanaged ODP.NET have the Oracle Client in one form or another.
This managed ODP.NET tutorial will teach the different ways to deploy with tnsnames.ora or not, but still connect to an Oracle DB. See the "Deploying a ODP.NET, Managed Driver Application" section specifically.
thanks for your answer. I read tutorial and tried to build a MVVM WPF application using a ODP.NET Managed Driver connection using the TNS approach. So, I wrote a tnsnames.ora file containing the connection string for my DB and copied it into my app /bin/debug directory.
There must be something else I didnt understand, because when I try to run the deployed app (http://deployserver/myapp), it just works on my computer (having ODP.NET Managed Driver installed in C:\windows\Microsoft .NET\assembly\GAC_32), but does not in other users' computers, where ODP.NET Managed Driver is not installed.
I included Oracle.ManagedDataAccess.dll and Oracle.ManagedDataAccessDTC.dll in my deployment, but this seems not enough.What more must I do to get my goal?
You either have to run the the Oracle ODAC GUI installer or the xcopy install.
.NET data providers are atypical .NET assemblies. They have additional configuration settings since they occupy a central part of the .NET Framework.
If you use the xcopy install, you can open the text batch file and see what manual configuration steps are done and customize these yourself if you prefer, but you don't have to.
I supposed that installing ODP.NET Managed Driver was enough to run my application.
Anyway, I just installed ODAC 220.127.116.11.2 xCopy for 64-bit machine; but I dont know how to include dll's into my project deployment. This is what I find on my server directory
Application Files (directory)
Application Files/TestView_[lastversion] folder contains theese files
IIS is configured so that, when the user links to the website, TestView.application is run.
Is there something missing in my deploy?
Looks like you have made a ClickOnce deployable application. If you include Oracle.ManagedDataAccess.dll with 'Copy Local = True' you should have a working client in VS and you should see ClickOnce pick up your dependency and deploy it. On the Project Settings Publish-tab there is a 'Application Files' button you can click to view what automatically goes with. You can manually add/remove as you see fit.
Oracle.ManagedDataAccess.dll will be Any CPU, Oracle.ManagedDataAccessDTC.dll will not. You may get away with not using Oracle.ManagedDataAccessDTC.dll depending on your oracle usage. Most common scenarios do not require DTC.
Looking at your list of files, it seems to me your setup is correct. You have the necessary assemblies packaged with you. Is your deploy not working?
BTW. I would highly recommend not using tnsnames.ora for name resolution. You should look into using connection strings of type EZConnect string, i.e. 'Data Source = //mydbserver/orcl' Oracle connection strings - ConnectionStrings.com It's SO much easier (and one file less to worry about)!
Im really struggling with this issue. I excluded Oracle.ManagedDataAccessDTC.dll from project references and left Oracle.ManagedDataAccess.dll with CopyLocal=True option. Building, publishing and running app from my computer was ok; running app from a clean computer still cause the same error. Theese are the resulting debug messages
"Unable to find the requested .NET Framework Data Provider. It may not be installed"
StackTrace: "at System.Data.Common.DBProviderFactories.GetFactory(String providerInvariantName)"
ClickOnce doesn't allow machine-wide changes, only per user level changes. That's fine if you call ODP.NET directly. However, if you want to use ODP.NET indirectly via Entity Framework, you need to register ODP.NET with .NET Framework. Otherwise, EF won't know that ODP.NET exists on the machine and how to call it. That generally requires a machine-level change by adding the ODP.NET, Managed Driver config entry in the <DbProviderFactories> section in your machine.config as the Oracle installer automatically does.
You can manually add the <DbProviderFactories> entry yourself to the app.config file if you'd like. However, there may be other configuration steps you will need. Essentially, you would be manually re-creating the Oracle install/config step by step, which is really a waste of time when it's already been automated for you in either GUI or script form.
Save yourself the trouble and install ODP.NET through one of these installers on the target machine. From there, run ClickOnce to install your EF application.
for "target machine" I guess you mean the development computer.
I installed 18.104.22.168.0 version of OPD.NET following the installation instructions, then I added an entry in <DbProviderFactories> both in TestView, App.Config and in machine.config. Here is the code snippet added
type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=22.214.171.124, Culture=neutral, PublicKeyToken=89b483f429c47342" />
<remove invariant="Oracle.DataAccess.Client" />
<add name="ODP.NET, Managed Driver" invariant="Oracle.DataAccess.Client"
description="Oracle Data Provider for .NET, Managed Driver"
type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=126.96.36.199, Culture=neutral, PublicKeyToken=89b483f429c47342" />
<dataSource alias="MYDB" descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=....)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=....)))"/>
<add name="bool" precision="1"/>
<add name="byte" precision="2" />
<add name="int16" precision="5" />
<add name="CinemaDataContext" connectionString="metadata=res://*/CinemaModel.csdl|res://*/CinemaModel.ssdl|res://*/CinemaModel.msl;provider=Oracle.ManagedDataAccess.Client;provider connection string="DATA SOURCE=MYDB;PASSWORD=PWD;PERSIST SECURITY INFO=True;USER ID=USR"" providerName="System.Data.EntityClient" />
<!--<add name="ODP.NET, Unmanaged Driver" invariant="Oracle.DataAccess.Client" description="Oracle Data Provider for .NET, Unmanaged Driver" type="Oracle.DataAccess.Client.OracleClientFactory, Oracle.DataAccess, Version=188.8.131.52, Culture=neutral, PublicKeyToken=89b483f429c47342" />-->
<add name="ODP.NET, Managed Driver" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=184.108.40.206, Culture=neutral, PublicKeyToken=89b483f429c47342" />
<add name="ODP.NET, Managed Driver" invariant="Oracle.DataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=220.127.116.11, Culture=neutral, PublicKeyToken=89b483f429c47342" />
<add name="Microsoft SQL Server Compact Data Provider" invariant="System.Data.SqlServerCe.3.5" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=18.104.22.168, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
<add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=22.214.171.124, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
I hope that deploying application to user's computer would install all it needs to connect to Database, but it seems not to happen, even if I add dll's as prerequisites.
the user's computer has Windows7 32bit and Microsoft .NET Framework 4.5.1. I dont know what was the error message because the user cannot debug the app. When we installed ODP.NET Managed Driver 126.96.36.199.0 for 32bit OS (running odp.net\managed\x86\configure.bat), the app worked. Just to be sure, we uninstalled the ODP.NET and the app did not work.
So, now we can be sure that our issue is how to make the correct ODP.NET Managed Driver (32bit or 64bit) be installed when the user run the application. It would be unreasonable enforce the users to install drivers manually. I thought that including the dll's as prerequisites sufficed, but it doesnt work.
maybe I found a solution!
I did what explained in this article: oracle - Deploying and Configuring ODP.NET to work without installation with Entity Framework - Stack Overflow
and using ODP.NET Managed Driver I got to make my app work to several clients (both 64bit and 32bit OS).
Now I wish to improve performance (DB connection seems quite slow) and allow the users to download updates automatically (now there is a delay between publishing a new version and making it visible to the users), but I can consider the in-topic issue resolved
thank you all for help
Nice to hear you are making headway. If your Oracle access is slow you should know that from the client to the server you are using Oracle proprietary protocol format that is known to be quite slow and very sensitive to latency. From my experience a few ms network latency is fine, but 10-20 ms will start showing up as slow. That is especially true for application frameworks i.e. that generate queries in a way that may not always be optimal.
I think you will see many solutions out in the wild where n-tier technology is applied such that you will find some kind of "application server" in between the Oracle database and the clients. The application server will be the only Oracle client and will contain EF framework etc. It may also hold caches to further increase performance. The clients then communicate with the application server to query for data of perform actions using some kind of communication mechanism, e.g. WCF. The thing here is that almost always can you place the application server close to the database and thus reduce the latency. The latency for the clients may not be so easily changed. This also means you do not need to deploy EF and Oracle assemblies, reducing the size of the ClickOnce installation.
Scroll one page down to see a description of 5-tiers, usually simple apps may separate out only 3.
As for the delay when publishing a new version, well your new version only gets picked up when the app is started. That is how ClickOnce work. You can then upgrade before the app starts, or continue with the old app and upgrade upon next restart. There is also an option for minimum version that can be used for forcing an upgrade at startup. If you need to detect upgrades during the time the application is running you can use the ClickOnce deployment API and check for updates programmatically; How to: Check for Application Updates Programmatically Using the ClickOnce Deployment API