I'm using FSharp.Data.SqlClient and trying to move my connectionString from a [<Literal>] to the app.config.
My app.config looks like this
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Test;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
</configuration>
And my SqlCommandProvider looks like the below, which should be correct according to http://fsprojects.github.io/FSharp.Data.SqlClient/configuration%20and%20input.html
new SqlCommandProvider<"SELECT ...",
ConnectionStringOrName = "name=DefaultConnection",
SingleRow = true,
AllParametersOptional = true>(??????)
Now the question is. What goes in the last part, the ?????? part.
I tried "name=DefaultConnection" but it gives me a runtime error with name being unsupported.
I can't seem to find any documentation explaining what goes there.
Update
Instaed of fixnig the issue I found this workaround.
https://fsprojects.github.io/FSharp.Configuration/
I don't get the purpose of ConnectionStringOrName if you have to supply the connection string anyway. Also why do you have to specify it twice. Makes very little sense to me :(
When using type providers, you often need two separate data sources:
Compile-time one that is used when you are editing the code and compiling the code. The type provider uses this connection or data source to infer the schema of the data - in case of SQL provider, this is connection to the database that is used to check that all your column names exist etc.
Run-time one is used when you actually run the program after it is deployed somewhere. This is where you'll read the actual data from.
The reason why you need two is that the run-time data source may be determined at runtime and it may not be accessible at compile-time (you typically have access to a dev database, but not to production database). The compile-time connection needs to be a constant, so that the provider can use it (when compiling your code) without running any part of your code.
In case of the SQL command provider:
type SelectCmd = SqlCommandProvider<"SELECT ...",
ConnectionStringOrName = "name=DefaultConnection",
SingleRow = true,
AllParametersOptional = true>
let cmd = new SelectCmd(??????)
"name=DefaultConnection" tells the provider to use an app.config key at compile-time
????? is where you need to specify the run-time connection string
To read the connection string from app.config, you can use the standard .NET methods like using ConfigurationManager:
open System.Configuration
let conn = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
let cmd = new SelectCmd(conn)
Something like this would not work when passing the connection string to the SqlCommandProvider, because this needs to run some code to read the string and that's only possible at runtime. That's why the SQL command provider has a handy option to specify name=DefaultConnection as a special string.
Related
Seems like a pretty trivial question, but to my surprise I found no mention of this on the web.
I've got an Nunit test project (that someone else wrote and I don't want to change too much), that I need to debug. These tests depend on environment variables that they read using Environment.GetEnvironmentVariable.
My question is: is there a way I can pass environment variables when debugging tests in Visual Studio?
I know I can pass environment variables when I debug an executable project through Project Properties->Debug, but this doesn't take effect when running tests (e.g. via Test Explorer). I also know I can pass test parameters through a .runsettings files, but these are accessible only through the TestContext class.
I also know I can pass test parameters through a .runsettings files, but these are accessible only through the TestContext class.
You can also specify environment variables in the .runsettings file:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<EnvironmentVariables>
<YOUR_VARIABLE>Value for your variable</YOUR_VARIABLE>
<SOME_OTHER_VARIABLE>With another Value</SOME_OTHER_VARIABLE>
</EnvironmentVariables>
</RunConfiguration>
</RunSettings>
Alternatively (if you need to run code or calculate the value) you can implement a DataCollector which provides environment variables via ITestExecutionEnvironmentSpecifier
// Add a reference to nuget package `Microsoft.TestPlatform.ObjectModel`
// The assembly name must end with `Collector` (i.e. match `*collector.dll`)
[DataCollectorFriendlyName("my own example collector")]
[DataCollectorTypeUri("datacollector://myown/examplecollector/1.0")]
public class MyDataCollector : DataCollector, ITestExecutionEnvironmentSpecifier
{
public override void Initialize(
XmlElement configurationElement,
DataCollectionEvents events,
DataCollectionSink dataSink,
DataCollectionLogger logger,
DataCollectionEnvironmentContext environmentContext)
{
// inspect configurationElement for your custom settings
}
public IEnumerable<KeyValuePair<string, string>> GetTestExecutionEnvironmentVariables()
{
return new Dictionary<string, string>
{
["YOUR_VARIABLE"] = "your value",
};
}
}
You also configure your data collector via the .runsettings file:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<TestAdaptersPaths>path/where/to/find/your/collector</TestAdaptersPaths>
</RunConfiguration>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="my own example collector" uri="datacollector://myown/examplecollector/1.0">
<Configuration>
<SomeSettingHere/>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
If you want to change the environment vaiable when you are debugging a project without break it, you can try to set it in the system environment variable.
1), create a system environment variable called number
2) use this in your code:
string str= Environment.GetEnvironmentVariable("number",EnvironmentVariableTarget.Machine);
It will get the system environemnt variable number in your code.
3) start debugging this project and set a breakpoint on it, when you want to change the variable, you can change the value on the system environemnt variable number directly under Computer's properties.
After that,just move the cursor back to the code line, you can use the changed value.
=========================================
Update 1
When you change the value of system variable number, you should click OK to save the new value. And then move the cursor of the breakpoint back to get the new value.
Also, you should enable Edit and Continue option.
Possible?
Cannot find a "sink forwarder", where one sink can forward to several other sinks, possibly of the same type.
Serilogs documentation (https://github.com/serilog/serilog/wiki/AppSettings)
clearly states that
NOTE: When using serilog: keys need to be unique.*
so adding the same Seq sink several times doesnt seem to be a good idea.
I'm looking for the same concept as in log4net, where one logger can hold several appenders.
Unfortunately the <appSettings> config provider for Serilog doesn't support this case; the appSettings.json one does, if you're able to use it, otherwise configuring the sinks in code WriteTo.Seq(...).WriteTo.Seq(...) is the way to go.
Semi-workaround style of solution:
Put a "read these keys" in appsettigs
Example 1: Read one key
<add key="SerilogToHttpKeys" value="MyMachineA" />
Example 2 (which solves the problem): Read many keys
<add key="SerilogToHttpKeys" value="MyMachineA, MyLocalMachine, MachineOnTheMoon" />
Both cases "points" to an unlimited number of keys, that are then read via code (see 2) and hence be tweaked w/out recompiling
<add key="MyLocalMachine" value="http://localhost:5341/;juzOPqqqqqqqq" />
<add key="MyMachineA" value="http://10.107.14.57:5341/;m8QVnDaqqqqqqqqqqqqq" />
<add key="MachineOnTheMoon" value="http://10.107.14.62:5341/;Ah0tSzqqqqqqqqqqqq"
Loop the keys in code - each key points to a http address with an API key, which is used for logging to Seq, but change the structure of each entry, and you could log to file ect.
foreach (var aKey in System.Configuration.ConfigurationManager.AppSettings.Get("SerilogToHttpKeys")
.Split(',')//Use , as separator
.Select(s => s.Trim()))
{
var fields = System.Configuration.ConfigurationManager.AppSettings.Get(aKey);
var separator = ';';
string serverUrl = fields.Split(separator)[0];
string apiKey = fields.Split(separator)[1];
loggerConfiguration = loggerConfiguration.WriteTo.Seq(serverUrl: serverUrl, apiKey: apiKey);
}
I use this for logging both to my server and my dev machine at the same time - its easier to keep the localhost Seq open when errors occour, and see if I can find them there instead of logging into the server. However, in case my devmachine is not online, I have the logs on the server as well. Off course, if more than one persons accesses the server licenses are needed for Seq, but in a simple "one dev, one dev-machine, one server" it works.
I have a solution with an MVC project containing a Services project on top of a Core project.
I just added a Unit Tests project and referenced Core and Services - I'm trying to test Services.
I have a basic call in the test:
public class CrudTests
{
private readonly SetServices _setService = new SetServices();
[TestMethod]
public void TestMethod()
{
_setService.CreateSet("Test Set", "Test Set Details", null);
Which ends up failing because the test can't connect to a database. My config has this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.\;Initial Catalog=Project.Services.Tests;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\Project.Services.Tests.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
I've tried by creating the database Project.Services.Tests and then running, but I get this:
Message=Database 'C:\Program Files\Microsoft SQL
Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\App.Services.Tests.mdf'
already exists. Choose a different database name. Cannot attach the
file
'C:\PROJECTS\App\App\Services.Tests\bin\Debug\Services.Tests.mdf'
as database 'App.Services.Tests'.
Source=.Net SqlClient Data Provider
ErrorCode=-2146232060
Class=16
LineNumber=65536
Number=1801
Procedure=""
Server=.\
State=2
StackTrace:
I tried deleting the database and letting the test do it's thing, and I get this:
A file activation error occurred. The physical file name
'\Project.Services.Tests.mdf' may be incorrect. Diagnose and correct
additional errors, and retry the operation.
How can I get this working properly?
In Unit Testing you must test the code without any dependency such as database or file system etc.
unit test means testing only that part of code independently.
if you want to test your code by its integration to database you must create Integration Test.
that means you should create an initializing for database usage before running test and a tear down for diposing resources after finishing tests.
maybe this link help you more to understand the difference between Unit Test and Integration Test
you should just fix the connection string and it should work, You are attaching the database file from |DataDirectory| of the test project,
Hi this is my scenario,
I am trying to migrate an app from JBoss5 to JBoss7.
I am using jboss-as-7.1.1.Final.
The error I am getting is:
No EJB receiver available for handling [appName:,modulename:myapp-ejb,distinctname:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext#6b9bb4bb
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:584) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:119) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:136) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
I have looked at several discussions with the same error message but I just cant figure out what I am doing wrong.
In the deployments directory I have only one myapp.war. I do not deploy a .ear file. I have a dependency (myapp-ejb.jar) deployed as a module.
I have followed the instructions from https://docs.jboss.org/author/display/AS71/How+do+I+migrate+my+application+from+AS5+or+AS6+to+AS7 in section "Migrate EAP 5 Deployed Applications That Make Remote Invocations to AS 7".
SERVER
In the myapp-ejb.jar I have a bunch of JNDI names like:
public static final String ACCOUNT_REMOTE = "ejb:/myapp-ejb//AccountBean!com.company.myapp.ejb.account.AccountRemote";
The lookup is done from the client by invoking this static method which is defined in myapp-ejb.jar:
public static AccountRemote getAccountRemote() throws NamingException {
if (accountRemote == null){
InitialContext ic = new InitialContext();
Object ref = ic.lookup(JNDINames.ACCOUNT_REMOTE);
accountRemote = (AccountRemote) PortableRemoteObject.narrow(ref, AccountRemote.class);
}
return accountRemote;
}
All remote interfaces are for stateless EJB like:
#Stateless
#Remote(AccountRemote.class)
public class AccountBean implements AccountRemote {
CLIENT
From the myapp.war I make a remote invocation to the myapp-ejb.jar using the above static method getAccountRemote().
In the myapp.war/WEB-INF directory I have added a jndi.properties and a jboss-ejb-client.properties.
The jndi.properties contains only one value:
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
The jboss-ejb-client.properties contains:
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port=4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
I have removed the security realm on remoting from the standalone.xml:
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
<connector name="remoting-connector" socket-binding="remoting" />
</subsystem>
I have added the JBOSS_HOME/bin/client/jboss-client.jar to the myapp.war/WEB-INF/lib.
The application deploys successfully without any errors but when I launch localhost:8080/ I get the No EJB receiver available for handling error.
Does anyone knows what I have missed? Any suggestions?
"EJB client API approach" for remote EJB invocation from one node to another node in clustered JBOSS:
------------------------------------------------------------------------------------
1. To call EJB from remote location we need to enable "remoting-ejb-receiver" on server side.
Please refer to “standalone_changes.xml” to know change details.
2. Also we need to register the "remoting-ejb-receiver" to the application, so that the application can receive remote EJB.
Please refer to “jboss-ejb-client.xml” section.
3. Now we need to call remote EJB in "EJB client API approach" way, which needs to have JNDI name pattern as:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fullclassname-of-the-remote-interface>
In our case it will be: ejb:myapp-ejb//node1/AccountBean!com.company.myapp.ejb.account.AccountRemote
Important to note that identification to remote location IP address is not based on InitialContext as InitialContext will not contain any IP address as normally happens with "remote://URL:Port".
The remote location identification is based on <distinct-name> passed in JNDI. JBOSS will internally identify the remote IP based on <distinct-name>.
Hence is required to provide unique <distinct-name> to the application running on different nodes.
Add "<distinct-name>${jboss.node.name}</distinct-name>" to “jboss-app.xml”. Make sure that jboss.node.name property is always unique.
But then jboss.node.name should be added as environmental property while server startup.
For test purpose we can provide hardcoded value like:
For node1: "<distinct-name>node1</distinct-name>" to “jboss-app.xml”.
For node2: "<distinct-name>node2</distinct-name>" to “jboss-app.xml”.
standalone_changes.xml:
------------------------------------------------------------------------------------
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
<outbound-connections>
<remote-outbound-connection name="remote-ejb-connection-host2" outbound-socket-binding-ref="remote-ejb-host2" username="xxx" security-realm="ejb-security-realm">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
...........
...........
</outbound-connections>
</subsystem>
...........
...........
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<outbound-socket-binding name="remote-ejb-host2">
<remote-destination host="${jboss.ejb.host2}" port="${jboss.ejb.host2.port}"/>
</outbound-socket-binding>
...........
...........
</socket-binding-group>
...........
...........
<management>
<security-realms>
<security-realm name="ejb-security-realm">
<server-identities>
<secret value="${jboss.ejb.remoting.password}"/>
</server-identities>
</security-realm>
...........
...........
</security-realms>
</management>
jboss-app.xml:
------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<jboss-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee">
<distinct-name>node1</distinct-name>
<security-domain>xyz</security-domain>
<unauthenticated-principal>guest</unauthenticated-principal>
<library-directory>lib</library-directory>
</jboss-app>
jboss-ejb-client.xml
------------------------------------------------------------------------------------
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.0">
<client-context>
<ejb-receivers>
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-host2"/>
<!-- <remoting-ejb-receiver outbound-connection-ref="${jboss.remote.outbound.connection.host3}"/> -->
</ejb-receivers>
</client-context>
</jboss-ejb-client>
For more details refer to:
"https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project" which tells us different way of remote EJB location.
You don't actually require jboss-client.jar if you are using JBOSS as your App server. Please add the following property to your initialContext or jndi.propeties file everything would be fine.
jboss.naming.client.ejb.context=true
also please remove the property unless you are calling from a standalone client or server other than Jboss.
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
Try with these settings.
I have my projects setup as follows (repository pattern):
myProj.Data (Contains the xDB.mdf) [Library]
myProj.Service (Uses myProj.Data) [Library]
myProj.WebApp (Uses myProj.Service) [ASP.NET Website]
In 1. I access my Database via Linq to Sql. The app.config looks like this:
<add name="XDbConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\XDb.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient" />
When I try to retrieve some data via the web, I get this error thrown from the Service Project:
An attempt to attach an auto-named database for file D:\MyProject\XDb.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.
From this code:
return (from p in repository.GetPostMedia() where p.PostId == postId select p).ToList();
Check in Management Studio that you don't have that database already attached, if so detach it and try again.
I moved the database from the myProj.Data into myProj.Web App_Data folder and it worked.