I have created an index in the azure portal and I am trying to access the index in my code to get the data. Everytime I do it I get a {System.Net.Sockets.SocketException (11001): No such host is known at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)}.
Is there anything I can do for this?
Below is my code
static void Main(string[] args)
{
Index();
}
public static DocumentSearchResult<SearchResult> Index()
{
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
IConfigurationRoot configuration = builder.Build();
string serviceName = configuration["SearchServiceName"];
string key = configuration["SearchServiceQueryApiKey"];
//Creating search client
SearchServiceClient serviceClient = new SearchServiceClient(serviceName, new SearchCredentials(key));
SearchIndexClient indexClient = new SearchIndexClient(serviceName, "cognitivesearchpoc", new SearchCredentials(key));
SearchParameters parameters;
DocumentSearchResult<SearchResult> results;
parameters = new SearchParameters() { Select = new[] { "*" } };
return indexClient.Documents.Search<SearchResult>("*");
}
The error message is telling you that the host name to which you’re trying to connect is incorrect. Use just the host name portion of your service endpoint as the service name. In your case, that’s just “devglobalsearch” without the DNS suffix.
Related
I have just started to use FluentMigration for my current project. I wrote my first migration but I have some trouble writing a unit test for it.
Here is some sample code:
private ServiceProvider CreateServiceProvider()
{
return new ServiceCollection()
.AddLogging(lb => lb.AddFluentMigratorConsole())
.AddFluentMigratorCore()
.ConfigureRunner(
builder => builder
.AddSQLite()
.WithGlobalConnectionString("Data Source=:memory:;Version=3;New=True;")
.WithMigrationsIn(typeof(MigrationOne).Assembly))
.BuildServiceProvider();
}
private void PerformMigrateUp(IServiceScope scope)
{
var runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();
runner.MigrateUp(1);
}
[Test]
public void ShouldHaveTablesAfterMigrateUp()
{
var provider = this.CreateServiceProvider();
using (var scope = provider.CreateScope())
{
this.PerformMigrateUp(scope);
// here I'd like to test if tables have been created in the database by the migration
}
}
I don't know how (or if it is possible) to access the current database connection so I can perform a query. Any suggestions would be helpful. Thanks.
Ok, I found a solution. I have to use the Process method of the runner's processor to perform my own sql query.
It looks like this:
private ServiceProvider CreateServiceProvider()
{
return new ServiceCollection()
.AddLogging(lb => lb.AddFluentMigratorConsole())
.AddFluentMigratorCore()
.ConfigureRunner(
builder => builder
.AddSQLite()
.WithGlobalConnectionString(#"Data Source=:memory:;Version=3;New=True;")
.WithMigrationsIn(typeof(MigrationDate20181026113000Zero).Assembly))
.BuildServiceProvider();
}
[Test]
public void ShouldHaveNewVersionAfterMigrateUp()
{
var serviceProvider = this.CreateServiceProvider();
var scope = serviceProvider.CreateScope();
var runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();
runner.MigrateUp(1);
string sqlStatement = "SELECT Description FROM VersionInfo";
DataSet dataSet = runner.Processor.Read(sqlStatement, string.Empty);
Assert.That(dataSet, Is.Not.Null);
Assert.That(dataSet.Tables[0].Rows[0].ItemArray[0], Is.EqualTo("Migration1"));
}
This is an old question but an important one. I find it strange that I couldnt find any documentation on this.
In any case here is my solution which I find to be a bit better as you dont need to rely on the runner. Since you dont need that the options open up hugely for constructor arguments.
Firstly make sure you install Microsoft.Data.Sqlite or you will get a strange error.
SQLite in memory databases exist for as long as the connection does - and 1 database per connection on first glance. Actually though there is a way to share the database between connections as long as at least 1 connection is open at all times according to my experiments. You just need to name it.
https://learn.microsoft.com/en-us/dotnet/standard/data/sqlite/connection-strings#sharable-in-memory
So to begin with I created a connection that will stay open until the test finishes. It will be named using Guid.NewGuid() so that subsequent connections will work as expected.
var dbName = Guid.NewGuid().ToString();
var connectionString = $"Data Source={dbName};Mode=Memory;Cache=Shared";
var connection = new SqliteConnection(connectionString);
connection.Open();
After that the crux of running the migrations is the same as previously answered but the connection string uses the named database:
var sp = services.AddFluentMigratorCore()
.ConfigureRunner(fluentMigratorBuilder => fluentMigratorBuilder
.AddSQLite()
.WithGlobalConnectionString(connectionString)
.ScanIn(AssemblyWithMigrations).For.Migrations()
)
.BuildServiceProvider();
var runner = sp.GetRequiredService<IMigrationRunner>();
runner.MigrateUp();
Here is a class I use to inject a connection factory everywhere that needs to connect to the database for normal execution:
internal class PostgresConnectionFactory : IConnectionFactory
{
private readonly string connectionString;
public PostgresConnectionFactory(string connectionString)
{
this.connectionString = connectionString;
}
public DbConnection Create()
{
return new NpgsqlConnection(connectionString);
}
}
I just replaced this (all hail dependency inversion) with:
internal class InMemoryConnectionFactory : IConnectionFactory
{
private readonly string connectionstring;
public InMemoryConnectionFactory(string connectionstring)
{
this.connectionstring = connectionstring;
}
public DbConnection Create()
{
return new SqliteConnection(connectionstring);
}
}
where the connection string is the same named one I defined above.
Now you can simply use that connection factory anywhere that needs to connect to the same in memory database, and since we can now connect multiple times possibilities for integration testing open up.
Here is the majority of my implementation:
public static IDisposable CreateInMemoryDatabase(Assembly AssemblyWithMigrations, IServiceCollection services = null)
{
if (services == null)
services = new ServiceCollection();
var connectionString = GetSharedConnectionString();
var connection = GetPersistantConnection(connectionString);
MigrateDb(services, connectionString, AssemblyWithMigrations);
services.AddSingleton<IConnectionFactory>(new InMemoryConnectionFactory(connectionString));
return services.BuildServiceProvider()
.GetRequiredService<IDisposableUnderlyingQueryingTool>();
}
private static string GetSharedConnectionString()
{
var dbName = Guid.NewGuid().ToString();
return $"Data Source={dbName};Mode=Memory;Cache=Shared";
}
private static void MigrateDb(IServiceCollection services, string connectionString, Assembly assemblyWithMigrations)
{
var sp = services.AddFluentMigratorCore()
.ConfigureRunner(fluentMigratorBuilder => fluentMigratorBuilder
.AddSQLite()
.WithGlobalConnectionString(connectionString)
.ScanIn(assemblyWithMigrations).For.Migrations()
)
.BuildServiceProvider();
var runner = sp.GetRequiredService<IMigrationRunner>();
runner.MigrateUp();
}
private static IDbConnection GetPersistantConnection(string connectionString)
{
var connection = new SqliteConnection(connectionString);
connection.Open();
return connection;
}
Then here is a sample test:
public Test : IDisposable {
private readonly IDisposable _holdingConnection;
public Test() {
_holdingConnection = CreateInMemoryDatabase(typeof(MyFirstMigration).Assembly);
}
public void Dispose() {
_holdingConnection.Dispose();
}
}
You may notice that the static factory returns a custom interface. Its just an interface that extends the normal tooling I inject to repositories, but also implements IDisposable.
Untested bonus for integration testing where you will have a service collection created via WebApplicationFactory or TestServer etc:
public void AddInMemoryPostgres(Assembly AssemblyWithMigrations)
{
var lifetime = services.BuildServiceProvider().GetService<IHostApplicationLifetime>();
var holdingConnection= InMemoryDatabaseFactory.CreateInMemoryDapperTools(AssemblyWithMigrations, services);
lifetime.ApplicationStopping.Register(() => {
holdingConnection.Dispose();
});
}
I have a multi-tenant application where one DB per tenant with one Master DB is configured. I load all the data sources in applications something like this :
#ConfigurationProperties(prefix = "spring.datasource")
#Bean
public DataSource dataSource() {
if(LOGGER.isInfoEnabled())
LOGGER.info("Loading datasources ...");
DataSource ds = null;
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
// load MASTER datasource
ds = dataSourceLookup.getDataSource(properties.getJndiName());
// load other TENANTs DB details
JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
List<GroupConfig> groupConfigs = jdbcTemplate.query(
"select * from master.tblTenant where IsActive=1 and ConfigCode in ('DB_URL','DATASOURCE_CLASS','USER_NAME','DB_PASSWORD') order by 2",
new ResultSetExtractor<List<GroupConfig>>() {
public List<GroupConfig> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<GroupConfig> list = new ArrayList<GroupConfig>();
while (rs.next()) {
GroupConfig groupConfig = new GroupConfig();
groupConfig.setGroupConfigId(rs.getLong(1));
groupConfig.setGroupCode(rs.getString(2));
groupConfig.setConfigCode(rs.getString(3));
groupConfig.setConfigValue(rs.getString(4));
groupConfig.setIsActive(rs.getBoolean(5));
list.add(groupConfig);
}
return list;
}
});
int propCount = 1;
Map<String, Map<String, String>> groups = new HashMap<String, Map<String, String>>();
Map<String, String> temp = new HashMap<String, String>();
for (GroupConfig config : groupConfigs) {
temp.put(config.getConfigCode(), config.getConfigValue());
if (propCount % 4 == 0) {
groups.put(config.getGroupCode(), temp);
temp = new HashMap<String, String>();
}
propCount++;
}
// Create TENANT dataSource
Map<Object, Object> resolvedDataSources = new HashMap<Object, Object>();
for (String tenantId : groups.keySet()) {
Map<String, String> groupKV = groups.get(tenantId);
DataSourceBuilder dataSourceBuilder = new DataSourceBuilder(this.getClass().getClassLoader());
dataSourceBuilder.driverClassName(groupKV.get("DATASOURCE_CLASS")).url(groupKV.get("DB_URL"))
.username(groupKV.get("USER_NAME")).password(groupKV.get("DB_PASSWORD"));
//System.out.println(dataSourceBuilder.findType()); //class org.apache.tomcat.jdbc.pool.DataSource
if (properties.getType() != null) {
dataSourceBuilder.type(properties.getType());
}
if(LOGGER.isInfoEnabled())
LOGGER.info("Building datasource : "+tenantId);
resolvedDataSources.put(tenantId, dataSourceBuilder.build());
}
resolvedDataSources.put("MASTER", ds);
MultitenantDataSource dataSource = new MultitenantDataSource();
dataSource.setTargetDataSources(resolvedDataSources);
dataSource.setDataSourceLookup(dataSourceLookup);
dataSource.afterPropertiesSet();
if(LOGGER.isInfoEnabled())
LOGGER.info("Datasources initialization finished !");
return dataSource;
}
In controller I set respective data source as (similarly for TENANT datasources) :
TenantContext.setCurrentTenant("MASTER");
Issue : On server startup every thing works fine (both MASTER DB and TENANT specific queries), but once the server is idle for some time (few Hours) tenant specific calls starts failing (while MASTER DB connections still works fine) with error :
Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
Please help me to get rid off this exception. Thanks in advance.
I got the problem and solutions as well:
Why tenant connections was getting closed? Because Auto configurations(#ConfigurationProperties(prefix = "spring.datasource")) of spring-boot was not getting applied on the tenant DataSources which I was creating in code.
Resolution- I added new method to set the tomcat connection pool properties:
private DataSource buildDataSource(String driverClass, String url, String user, String pass){
PoolProperties p = new PoolProperties();
p.setUrl(url);
p.setDriverClassName(driverClass);
p.setUsername(user);
p.setPassword(pass);
p.setJmxEnabled(true);
p.setTestWhileIdle(false);
p.setTestOnBorrow(true);
p.setValidationQuery("SELECT 1");
p.setTestOnReturn(false);
p.setValidationInterval(30000);
p.setTimeBetweenEvictionRunsMillis(30000);
p.setMaxActive(100);
p.setInitialSize(10);
p.setMaxWait(10000);
p.setRemoveAbandonedTimeout(60);
p.setMinEvictableIdleTimeMillis(30000);
p.setMinIdle(10);
p.setLogAbandoned(true);
p.setRemoveAbandoned(true);
DataSource datasource = new DataSource();
datasource.setPoolProperties(p);
return datasource;
}
This solved my problem. But I'm curious to know if there is a way to apply AutoConfigurations while creating the objects in spring-boot.
I am implementing AppEngine server as a backend for my Android application. I use Datastore, I query it via Objectify service and I use Endpoints that I call via URL.
I have an entity User with properties like this:
#Id
Long id;
/**
* Name or nickname of the user
*/
public String name;
#Index
public String email;
#JsonIgnore
List<Key<User>> friends;
public User()
{
devices = new ArrayList<String>();
friendsWithKey = new ArrayList<Key<User>>();
}
public static User findRecordById(Long id)
{
return ofy().load().type(User.class).id(id).now();
}
#ApiMethod(name = "friends", httpMethod = "GET", path = "users/{userId}/friends")
public JSONObject getFriends(#Named("userId") String userId)
{
User user = User.findRecordById(Long.parseLong(userId));
JSONObject friendsObject = new JSONObject();
JSONArray jsonArray = new JSONArray();
JSONObject friend;
List<User> userList = new ArrayList<User>();
if (user.friendsWithKey != null)
{
for (Key<User> id : user.friendsWithKey)
{
friend = new JSONObject();
User user1 = User.findRecordById(id.getId());
userList.add(user1);
friend.put("name", user1.name);
friend.put("email", user1.email);
friend.put("id", user1.id);user1.lastTimeOnline.getTime());
jsonArray.add(friend);
}
friendsObject.put("friends", jsonArray);
}
return friendsObject;
}
It sometimes returns only a subset of friends. It is weird and I do not get where I could go wrong. If I get the User object from the DB, it already has a wrong List of Key values. But if I look into the database via console, I can see all of the users that ahve been added as friends.
I reaally need to fix this bug. Please, help.
It is very strange because it only happens once in a while and is non-deterministic in every way.
I am working on an MVC3 application database first approach . I would like to use one connection string to connect to database, based on some string (company name). Example: I have in my MSSQL Express 2012 this db: my_database_microsoft, my_database_oracle and so on..(those databases have same structure). On login page I have 3 input fields: username,password,company. I know how to build connection string dynamic with SqlConnectionStringBuilder and then use it on EntityConnectionStringBuilder
string providerName = "System.Data.SqlClient";
string serverName = "MY-PC\\SQL2012";
string databaseName = "my_database_"+form[company].toString();
.....
.....
entityBuilder.Provider = providerName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;
// Set the Metadata location.
entityBuilder.Metadata =#"res://*/Models.Model1.csdl|res://*/Models.Model1.ssdl|res://*/Models.Model1.msl";
using (EntityConnection conn =
new EntityConnection(entityBuilder.ToString()))
{
conn.Open();
// Console.WriteLine("Just testing the connection.");
conn.Close();
}
obracun_placEntities1.nameOrConnectionString = entityBuilder.ToString();
obracun_placEntities1 o = new obracun_placEntities1(entityBuilder.ToString());
I have made a partial class of my entety and give a constructor that take a nameOrConnectionString string as a parameter.
public partial class obracun_placEntities1
{
public string nameOrConnectionString { get; set; }
public obracun_placEntities1(string nameOrConnectionString)
: base(nameOrConnectionString ?? "obracun_placEntities1") { }
}
This works only in loginController but how can I use this in UsersController and all other controllers where I using obracun_placEntities1 db = new obracun_placEntities1(); > this take the default database from web.config. I would not like to save connection string to session or cookie and than pass it in every controler as a parameter.
private obracun_placEntities1 db = new obracun_placEntities1();
How can i achieve that i pass connection string in login controller and using this database in entire project.
One more problem occured when i want to use public static string nameOrConnectionString
and pass it to constructor. The problem is when I open application in Chrome and login as user1 I get all infromation from user1 database, but then I login in MS Explorere as user2 and get all data from user2 database. When i refresh chrome I get information from the user2 database not user1.
Model1.context.cs
public partial class obracun_placEntities1 : DbContext
{
public static string nameOrConnectionString { get; set; }
// public static string connection;
public obracun_placEntities1()
: base(nameOrConnectionString ?? "obracun_placEntities1")
{
}
Connecting to different Databases is best done using the DBconnection constructor on DBCOntext. If you look at the DBContext class you will see multiple constructor overloads. One allows the DBConnection to be supplied. So no entry in WEB.Config/App.Config is required.
See this post with sample code Same Context accessing different databases.
EDIT sample added:
public partial class obracun_placEntities1 : DbContext
{
// use THIS CONSTRUCTOR
protected obracun_placEntities1(DbConnection dbConnection, bool contextOwnsConnection)
: base(dbConnection, contextOwnsConnection)
{
}
}
}
// DONT USE THIS
// obracun_placEntities1.nameOrConnectionString = entityBuilder.ToString();
// obracun_placEntities1 o = new obracun_placEntities1(entityBuilder.ToString());`
// build the connection - note: it is NOT a connection string. it is a DBConnection!
conn = getDBConnection4SQLServer(DatabaseServer,Databasename)
obracun_placEntities1 o = new obracun_placEntities1(conn,true);
//====================================================================
public const string DefaultDataSource = "localhost";
public DbConnection getDBConnection4SQLServer(string dataSource, string dbName) {
var sqlConnStringBuilder = new SqlConnectionStringBuilder();
sqlConnStringBuilder.DataSource = String.IsNullOrEmpty(dataSource) ? DefaultDataSource : dataSource;
sqlConnStringBuilder.IntegratedSecurity = true;
sqlConnStringBuilder.MultipleActiveResultSets = true;
var sqlConnFact = new SqlConnectionFactory(sqlConnStringBuilder.ConnectionString);
var sqlConn = sqlConnFact.CreateConnection(dbName);
return sqlConn;
}
I finnaly getting it to work with this code.
My LoginController
[HttpPost]
public ActionResult Index(UPORABNIK model, FormCollection form)
{....}
public obracun_placEntities1(EntityConnection entityConnection)
: base(entityConnection, false)
{
}
I call EntityConnection conn = GetEntityConnDbName("ServerName", "FirmName").
_entities = new obracun_placEntities1(conn, false);
var uporabniki = from r in _entities.UPORABNIK.Where(r => r.ime == uporabnik && r.geslo == geslo && danes <= r.veljavnost).ToList()
select r;
I get the firmName from the post form so this work only in LoginController.But how can I use this constructor in all other Controllers? I get firm name only once in LoginControler, I tried to save it as cookie but then i can not read it in the constructor.
In my other Controller I use the default controller again. How can I tranfer conn to other Controllers?
private obracun_placEntities1 db = new obracun_placEntities1();
I would like to call like this
private obracun_placEntities1 db = new obracun_placEntities1(conn);
Or is there some better way?
I have a web form where I need to add, update, delete and read using a unique ID. So far I have managed to add, update and delete functions with little trouble.
However now I am having trouble getting my read function to work (understand I have a webform that has four text fields; ID, FIRSTNAME, SURNAME AND ADDRESS). Basically when an ID that has been previously created (using add button) is entered into the text field and the read button clicked it should update the other 3 text fields with the stored entries depending on the ID entered.
Here is my behind code (cs.) on the web form
protected void cmdRead_Click(object sender, EventArgs e)
{
// Create a reference to the Web service
DbWebService.WebService1 proxy = new DbWebService.WebService1();
// Create a person details object to send to the Web service.
string ADDRESS;
string SURNAME;
string FIRSTNAME;
string ID;
ADDRESS = txtAddress.Text;
SURNAME = txtSurname.Text;
FIRSTNAME = txtFirstname.Text;
ID = txtID.Text;
// Attempt to store in the Web service
bool rsp = proxy.ReadPerson(int.Parse(ID), FIRSTNAME, SURNAME, ADDRESS);
// Inform the user
if (rsp)
{
lblOutcome.Text = "Successfully read data.";
txtFirstname.Text = FIRSTNAME;
txtSurname.Text = SURNAME;
txtAddress.Text = ADDRESS;
}
else
{
lblOutcome.Text = "Failed to read data! Select a previously created ID!";
}
}
and here is my web function on the web service (which is where the SQL Server Express database is)
[WebMethod]
public bool ReadPerson(int ID, string FIRSTNAME, string SURNAME, string ADDRESS)
{
// In case of failure failure first
bool rtn = false;
// Connect to the Database
SqlConnection connection = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename='|DataDirectory|\Database.mdf';Integrated Security=True;User Instance=True");
// Open the connection
connection.Open();
// Prepare an SQL Command
SqlCommand command = new SqlCommand(String.Format("SELECT FIRSTNAME, SURNAME, ADDRESS FROM PersonalDetails WHERE ID = '{0}'", ID), connection);
// Execute the SQL command and get a data reader.
SqlDataReader reader = command.ExecuteReader();
// Instruct the reader to read the first record.
if (reader.Read())
{
// A record exists, thus the return value is updated
FIRSTNAME = (string)reader["FIRSTNAME"];
SURNAME = (string)reader["SURNAME"];
ADDRESS = (string)reader["ADDRESS"];
rtn = true;
}
// Close the connection
connection.Close();
// Return the result.
return (rtn);
}
Now the problem is when I click read I get a success message (using a label as you can see in the behind code) but the fields don't update, I assume this is because of the (rtn = true;) statement. Therefore I thought something like this might work:
rtn = (bool)reader["ADDRESS"];
However with this I get a specified cast is not valid, so I figure maybe the bool doesn't work in this context, I think it might work if I use string instead but how do I convert, I think rtn needs a value in regards to the reader right??
Basically I am just looking for a solution to which will update the text fields in the web form.
There are several problems with your code. The most obvious is that your code cannot ever return the data from the database. You are sending FIRSTNAME etc. to the web service - you are not returning them from the web service.
There is no reason to have a bool return from the service to tell you whether or not it succeeded. Let the service throw an exception if it failed. Instead, you should return the fields from the database as the return of the service.
In the service:
public class Person
{
public string FIRSTNAME {get;set;}
public string SURNAME {get;set;}
public string ADDRESS {get;set;}
}
[WebMethod]
public Person ReadPerson(int ID)
{
// ...
if (reader.Read())
{
// A record exists, thus return the value
Person p = new Person();
p.FIRSTNAME = (string)reader["FIRSTNAME"];
p.SURNAME = (string)reader["SURNAME"];
p.ADDRESS = (string)reader["ADDRESS"];
rtn = p;
}
connection.Close();
return rtn;
}
Also, you should not be using a WebMethod or an ASMX web service unless you have no choice. ASMX is a legacy technology which is kept around only for backwards compatability. It should not be used for new development. You should use WCF instead.
The other issues with your code are resolved below:
[WebMethod]
public Person ReadPerson(int id)
{
using (
var connection =
new SqlConnection(
#"Data Source=.\SQLEXPRESS;
AttachDbFilename='|DataDirectory|\Database.mdf';
Integrated Security=True;
User Instance=True")
)
{
connection.Open();
using (
var command =
new SqlCommand(#"
SELECT FIRSTNAME, SURNAME, ADDRESS
FROM PersonalDetails
WHERE ID = #id",
connection))
{
var idParameter =
command.Parameters.Add(
"#id", SqlDbType.Int);
idParameter.Value = id;
using (var reader = command.ExecuteReader())
{
if (!reader.Read())
{
return null;
}
return new Person
{
Firstname =
(string)
reader["FIRSTNAME"],
Surname =
(string)
reader["SURNAME"],
Address =
(string)
reader["ADDRESS"]
};
}
}
}
}
The main issue is that the SqlConnection, SqlCommand, and SqlDataReader all need to be instantiated inside of using blocks. This ensures that the objects are disposed of (closed) whether or not an exception is thrown.
Next, you should not get into the habit of building queries through string manipulation; not even using String.Format. That leaves you open to "SQL Injection" attacks. Using parameters resolves that problem. See "Commands and Parameters " in MSDN.
One last minor issue: I recommend that you get out of the habit of placing comments on obvious statements. For instance, it's not necessary to comment that Open opens the connection to the database, or that return returns a value.