I'm developing a software that will be used in different locations with different Servers. It differs in Server Name, Database name, etc.
Example:
Location 1 : Server Name: ChinaServer; Database Name: ChinaDB
Location 2 : Server Name: USServer; Database Name: USDB
Currently, I am using .ini file, I store the server name, database name and other configurations to it. I read it and use it runtime for my connection string. The problem here is that every time we switch locations, I need to change/edit the .ini file.
I'm asking everyone that has more experience that mine to give me other options or best approach on this matter.
Client's Environment : Windows 7
Developers : Windows 7, Visual Studio 2015, MS SQL, VB.NET
Thanks IA.
There's a couple of ways, each with their own advantages and disadvantages, the configuration file would work, could also store it in the registry of the server and read it that way. Or you could even use a My.Setting variable that can be updated in a settings page (probably not the most suitable for your situation)
You can get the basic idea from the The Twelve-Factor App "manifesto":
The twelve-factor app stores config in environment variables...
So what you need is to establish a machine-wide (setx /M NAME VALUE) environment variable which you'll later use like this:
var connectionString = Environment.GetEnvironmentVariable("MY_APP_CONNECTION_STRING");
var dbContext = new DbContext(connectionString);
You can use the SQL Server enumerator in System.Data.Sql, and run a query to get the database names. From there bind those lists to combo boxes, and use a SqlConnectionStringBuilder to keep track of your connection settings. You can save them to disk, or just ask the user to choose the server and database. Note that the enumerator is not guaranteed to always find all servers, so make sure you have a way to enter it manually if necessary.
private SqlConnectionStringBuilder _connString = new SqlConnectionStringBuilder();
private void RefreshConnectionString()
{
_connString.ApplicationName = AppDomain.CurrentDomain.ApplicationIdentity.FullName;
_connString.ApplicationIntent = ApplicationIntent.ReadWrite;
_connString.DataSource = GetSqlDatasources().FirstOrDefault();
_connString.InitialCatalog = GetSqlDatabases().FirstOrDefault();
_connString.AsynchronousProcessing = true;
_connString.ConnectTimeout = 5;
_connString.IntegratedSecurity = true;
_connString.Pooling = true;
}
private IEnumerable<string> GetSqlDatabases()
{
using (var conn = new SqlConnection(_connString.ConnectionString))
{
using (var cmd = new SqlCommand(#"SELECT [name] FROM sys.databases WHERE [name] NOT IN ('master', 'model', 'msdb', 'tempdb')", conn))
{
var dbnames = new List<string>();
try
{
conn.Open();
var reader = cmd.ExecuteReader();
while (reader.Read()) dbnames.Add(reader.GetString(0));
}
catch {}
return dbnames;
}
}
}
private IEnumerable<string> GetSqlDatasources()
{
var sqlEnum = SqlDataSourceEnumerator.Instance;
return sqlEnum.GetDataSources().Rows.OfType<DataRow>().Select(row => row[0].ToString());
}
Related
I'd like to build a back end system that allows me to run each report every night and then query the execution log to see if anything failed. I know you can build out subscriptions for these reports and define parameters etc but is there a way to execute each report from the ReportServer database using TSQL without building out each subscription?
I understand that your overall goal is that you want to automate this and not have to write a subscription for every report. You say you want to do it in T-SQL, but is that required to meet your overall goal?
If you can accept, say .Net, then you can use the System.Data.SqlClient.SqlConnection and related classes to query your report server catalog and fetch a listing of all your reports.
Then you can use System.Net.WebClient or similar tool to attempt to download a pdf of your report. From there you can either read your execution log, or catch the error in the .Net Code.
EDIT
Well, since you accepted the answer, and it seems you may go this route, I'll mention that if you're not familiar with .net, it may be a long path for you. Here's a few things to get you started.
Below is a c# function utilizing .Net that will query the report catalog. If safeImmediate is set to true, it will only capture reports that can be run immediately, as in there are no parameters or the defaults cover the parameters.
IEnumerable<string> GetReportPaths(
string conStr,
bool safeImmediate // as in, you can exexute the report right away without paramters
) {
using (var con = new SqlConnection(conStr))
using (var cmd = new SqlCommand()) {
cmd.Connection = con;
cmd.CommandText = #"select path from catalog where type=2";
con.Open();
if (safeImmediate)
cmd.CommandText = #"
select path
from catalog
cross apply (select
params = convert(xml, Parameter).value('count(Parameters/Parameter)', 'int'),
defaults = convert(xml, Parameter).value('count(Parameters/Parameter/DefaultValues/Value)', 'int')
) counts
where type = 2
and params = defaults
and path not like '%subreport%' -- this is not standard. Just works for my conventions
";
using (var rdr = cmd.ExecuteReader())
while (rdr.Read())
yield return rdr["path"].ToString();
}
}
The next function will download a report given proper paths passed to it:
byte[] DownloadReport (
WebClient wc,
string coreUrl,
string fullReportPath,
string parameters = "" // you won't use this but may come in handy for other uses
) {
var pathToViewer = "ReportServer/Pages/ReportViewer.aspx"; // for typical ssrs installs
var renderOptions = "&rs:Format=pdf&rs:Command=Render"; // return as pdf
var url = $#"{coreUrl}/{pathToViewer}?{fullReportPath}{parameters}{renderOptions}";
url = Uri.EscapeUriString(url); // url's don't like certain characters, fix it
return wc.DownloadData(url);
}
And this utilizes the functions above to find what's succeeding and whats not:
var sqlCon = "Server=yourReportServer; Database=ReportServer; Integrated Security=yes"; // or whatever
var ssrsSite = "http://www.yourSite.org";
using (var wc = new WebClient()) {
wc.UseDefaultCredentials = true; // or whatever
int loops = 3; // get rid of this when you're ready for prime-time
foreach(var path in GetReportPaths(sqlCon, true)) {
try {
DownloadReport(wc, ssrsSite, path);
Debug.WriteLine($"Success with: {path}");
}
catch(Exception ex) { // you might want to get more specific
Debug.WriteLine($"Failed with: {path}");
}
if (loops-- == 0)
break;
}
}
Lots to learn, but it can be very beneficial. Good luck.
I am trying my hands on Windows phone 8 applications and I am stuck into a weird situation here. I am using sqlite in order to create sqlite db and add values into the database. I am able to create the database and add the values in the database successfully but I am having a weird situation here.
Everytime I close the emulator and start the project again the database gets created again which should not be happening because I created the db the very first time I run the application.
Does anybody know why, and how I can prevent it from recreating the database each time?
public string DB_PATH = Path.Combine(Path.Combine(ApplicationData.Current.LocalFolder.Path, "aa.sqlite"));
private SQLiteConnection dtCon;
public MainPage()
{
InitializeComponent();
CreateDatabase();
dtCon = new SQLiteConnection(DB_PATH);
var tp = dtCon.Query<Contacts>("select * from contacts").ToList();
}
private async void CreateDatabase()
{
bool isDatabaseExisting = false;
//Checking if database already exists
try
{
Windows.Storage.StorageFile storagefile = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync("aa.sqlite");
isDatabaseExisting = true;
}
catch
{
isDatabaseExisting = false;
}
//if not exists then creating database
if (!isDatabaseExisting)
{
String str = System.IO.Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "sqlite.db");
AddDataToDB(DB_PATH);
}
}
private void AddDataToDB(string str)
{
// Create the database connection.
dtCon = new SQLiteConnection(str);
// Create the table Task, if it doesn't exist.
dtCon.CreateTable<Contacts>();
Contacts oContacts = new Contacts();
oContacts.Name = "dfgdf";
oContacts.Detail = "asdfsf";
dtCon.Insert(oContacts);
}
I'm pretty sure when you close your emulator and restart, you're basically just uninstalling the application. Which is why your files or not there anymore -- as it looks like you're storing your data in isolated storage. I do not know if there is anyway around this.
You can buy a very cheap Windows 8/8.1 Phone and the files will persist until you manually uninstall the test application.
As #Chubosaurus says, closing and re-opening the emulator will remove all the apps. You can generally keep it running as long as you want and keep re-deploying your app to the emulator (although obviously rebooting the host PC will kill it).
You can save and restore the data from your emulator image via the ISETool command. See more here
Try adding Console.WriteLine("True"); and Console.WriteLine("False"); into the expected places after checking isDatabaseExisting to see/understand what the code path really is.
i have created the data base in windows phone 7 and it works me fine
after rebuild the application it says that
The database file cannot be found. Check the path to the database. [ Data Source = \Applications\Data\6157CB94-31D3-4E6F-BFC3-78BE1549C10A\Data\IsolatedStore\amit.sdf ]
my code for db string is
` private const string Con_String = #"isostore:/amit.sdf";`
how to solve this pls give me any suggestion to solve this problem
Have you checked this sample How to create a basic local database app for Windows Phone?
they use this path for create the db
//Specify the connection string as a static, used in main page and app.xaml.
public static string DBConnectionString = "Data Source=isostore:/ToDo.sdf";
and also don't forget to check if the db exists
//Create the database if it does not exist.
using (ToDoDataContext db = new ToDoDataContext(ToDoDataContext.DBConnectionString))
{
if (db.DatabaseExists() == false)
{
//Create the database
db.CreateDatabase();
}
}
I'm automating UI tests to my Silverlight App and I'm using Visual Studio 2010 for it. Some tests required a setup to my Oracle Database.
Things i've done:
1 - A setup.sql file where I connect to my Database and perform actions on it. I had this file as an existing item to my project and I add as a Deployment on TestSettings.
Code:
CONNECT USERNAME#DATABASE,
CREATE TABLE TABLE_NAME,
EXIT
2 - A set.bat file where I call the setup.sql file. I had the path of this file on Setup and Cleanup tab on TestSetings.
Code:
sqlcmd -S MARIALISBOA -i setup.sql
3 - I wrote a TestInitilize method on my TestClass.
Code:
[TestInitialize()]
public void Initialize()
{
System.Diagnostics.Process.Start("setup.bat");
}
4 - I connected do my Database throw Visual Studio (Data -> Add New Data Source).
I run a test on Visual Studio but the class isn't created on my database.
Could anyone help me? I'm trying to solve this problem since Monday and I starting to lose my mind
While it does not solve your initial problem, a solution would be to use something similiar to this;
Do not create the table within your tests. this should be created on install of the Test Environment
Clear down the table for each test you want to do using a Helper Method within the test.
For example (Please note that this is SQL Server, use OLE DB connection or similiar);
internal static object FireSqlStatement(string sqlStatement)
{
object result = null;
using (var cn = new SqlConnection(ConfigurationManager.ConnectionStrings[connectionString].ConnectionString))
{
cn.Open();
var cmd = new SqlCommand
{
CommandText = sqlStatement,
CommandType = CommandType.Text,
Connection = cn
};
result = cmd.ExecuteScalar();
cmd.Dispose();
cn.Close();
}
return result;
}
An example of how I use this within my test;
[Test]
public void GetUserTriggers()
{
//Insert Test Record
Helper.FireSqlStatement("INSERT INTO [Users].[Triggers] (Id) VALUES (1)");
var request = new GetTriggersRequest()
{
TriggerType = TriggerType.UserTrigger
};
var response = ServiceInvoker.Invoke<IReports,
GetTriggersRequest, GetTriggersResponse>(
"Reports",
request,
(proxy, req) => proxy.GetTriggers(req));
foreach (var t in response.Triggers)
{
Console.WriteLine(t.Id.ToString());
}
Assert.NotNull(response);
Assert.NotNull(response.Triggers);
Assert.Greater(response.Triggers.Count, 0);
}
In your case, you could call;
Helper.FireSqlStatement("TRUNCATE TABLE tableName");
Any good?
Not able to import application definition file!! Error: The metadata object with Name 'XYZ' and of Type 'LobSystemInstance' has a Property with Name 'DatabaseAccessProvider' that has either an invalid value or Type. Error was encountered at or just before Line: '10' and Position: '10'.
line 10 in ADF:
<"Property Name="DatabaseAccessProvider" Type="System.String">SqlOledb<"/Property>
Please give me ideas on how to display data from SQL Server 6.5 in Sharepoint?
The value of the node is invalid. You need to use SqlServer or OleDb. Check out this page for more information:
http://msdn.microsoft.com/en-us/library/ms550725(office.12).aspx
Im just starting on a similar task (so I found your unanswered question). I am trying to copy our documentation library in Sharepoint to an SQL db. Its not opening your file directly from SQL its using some c# code to setup a job which opens the sharepoint which may be what you are wanting.
There are two methods I have found so far:
One is to copy your data from sharepoint to a linked list in Access and then use the OLEDB methods in to open it.
Found here: C# Sync MS Access database to sql server
private static void BulkCopyAccessToSQLServer
(CommandType commandType, string sql, string destinationTable)
{
string connectionString = #"C:\Migration\Sharepoint Access SQL Batch Job\Database11.accdb";
using (DataTable dt = new DataTable())
{
string ConnStr = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Migration\Sharepoint Access SQL Batch Job\Database11.accdb;Jet OLEDB:Database Password=password";
//using (OleDbConnection conn = new OleDbConnection(Settings.Default.CurriculumConnectionString))
using (OleDbConnection conn = new OleDbConnection(ConnStr))
using (OleDbCommand cmd = new OleDbCommand(sql, conn))
using (OleDbDataAdapter adapter = new OleDbDataAdapter(cmd))
{
cmd.CommandType = commandType;
cmd.Connection.Open();
adapter.SelectCommand.CommandTimeout = 240;
adapter.Fill(dt);
adapter.Dispose();
}
using (SqlConnection conn2 = new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString))
using (SqlConnection conn2 = new SqlConnection(connectionString))
{
conn2.Open();
using (SqlBulkCopy copy = new SqlBulkCopy(conn2))
{
copy.DestinationTableName = destinationTable;
copy.BatchSize = 1000;
copy.BulkCopyTimeout = 240;
copy.WriteToServer(dt);
copy.NotifyAfter = 1000;
}
}
}
}
The other is to use the Microsoft.Sharepoint libraries and open your sharepoint directly from the c# then copy it into your SQL.
Found here: http://www.dotnetspark.com/kb/3573-fetching-lists-from-sharepoint-2010-site.aspx
using (SharePointclientObj.ClientContext ctx = new SharePointclientObj.ClientContext(clientContext))
{
//Get the site
SharePointclientObj.Web site = ctx.Web;
ctx.Load(site);
//Get Lists
ctx.Load(site.Lists);
//Query
ctx.ExecuteQuery();
//Fill List
foreach (SharePointclientObj.List list in site.Lists)
{
Console.WriteLine(list.Title);
}
}