Universe Entity Framework very slow to select - c#

I am going with the Entity Framework code first approach and am finding that queries to grab just 350 records or so is taking about 8 seconds. How can I speed this up? Is this Universe or Entity Framework that is being slow?
Entity Framework 5.0
U2.Data.Client 1.2.1
.Net Framework 4.5.1
RAMContext looks something like this :
public class RAMContext : DbContext
{
public RAMContext() { }
public DbSet<Policy> Policies { get; set; }
}
Here is the code to grab the entities :
List<Policy> policies = null;
Database.SetInitializer<RAMContext>(null);
using (RAMContext context = new RAMContext())
{
policies = (from p in context.Policies
where p.AGENT_NO == id
select p).ToList();
}
Here is the connection string :
<add name="RAMContext" connectionString="Database=<account>;UserID=<userid>;Password=<pwd>;Server=<server>;Pooling=false;ServerType=universe;ConnectTimeout=360;SleepAfterClose=300;PersistSecurityInfo=true" providerName="U2.Data.Client" />
AGENT_NO is indexed and the same query ran directly on the DB from TCL finishes almost instantly.
EDITED
After the comments from Rajan I tried the following :
policies = (from p in context.Policies
where p.AGENT_NO == id
select new PolicyModel
{
//Type = PolicyModel.Types)StringValue.GetEnumValueByStringValue(typeof(PolicyModel.Types), p.TYPE),
Insured = p.INSURED,
City = p.CITY,
State = p.STATE,
CancelDate = p.CANC_DT
//IsNew = PickHelper.PickYNNullToBool(p.NEW_RENEW_FLG)
});
I am able to make this select in under 3 seconds now, it appears. I also rebuilt the index on AGENT_NO and I believe that helped considerably.
Trying your second suggestion I get the following exception :
An exception of type 'System.IndexOutOfRangeException' occurred in U2.Data.Client.dll but was not handled in user code
Additional information:
Invalid index -1 for this U2ParameterCollection with Count=0.

Could you please try the following code? This code does not use Entity Framework (LINQ to Entity).
We want to see how UniVerse is behaving without Entity Framework.
You need to do the following:
Create C# Console application
Replace Program.cs file’ s content with the following code
Right Click->Add Reference -> C:\Program Files (x86)\Rocket Software\U2 Toolkit for .NET\U2 Database Provider\bin.NETFramework\v4.0\U2.Data.Client.dll
Change connection string
Change SQL syntax
Run the program. See below screen shot. It shows “Time Taken in Seconds”.
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using U2.Data.Client;
using System.Data;
using System.Diagnostics;
namespace DataAdapter
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("start.........................");
Stopwatch sw = new Stopwatch();
sw.Start();
U2ConnectionStringBuilder conn_str = new U2ConnectionStringBuilder();
conn_str.UserID = "administrator";
conn_str.Password = "pass";
conn_str.Server = "localhost";
conn_str.Database = "XDEMO";
conn_str.ServerType = "UNIVERSE";
conn_str.Pooling = false;
string s = conn_str.ToString();
U2Connection con = new U2Connection();
con.ConnectionString = s;
con.Open();
Console.WriteLine("Connected...");
U2Command cmd = con.CreateCommand();
cmd.CommandText = "SELECT * FROM PRODUCTS";
DataSet ds = new DataSet();
U2DataAdapter da = new U2DataAdapter(cmd);
da.Fill(ds);
sw.Stop();
TimeSpan elapsed = sw.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", elapsed.Hours, elapsed.Minutes, elapsed.Seconds, elapsed.Milliseconds / 10);
int nSec = elapsed.Seconds;
con.Close();
Console.WriteLine("Time Taken in seconds:" + elapsedTime);
Console.WriteLine("End........................... ");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
Console.WriteLine("Enter to exit:");
string line = Console.ReadLine();
}
}
}
}

Related

Unable to capture the query details using XtendedEvents C#

I am trying to capture the entity framework queries via SQL Server trace using C# that are getting executed during my automation test run. When I run the below code ,I am getting the exception
Issue
The queries that are getting executed in the background are not getting captured. Any other thing that I can try to get the select /insert/ update queries that are running in the background
Code
class Program
{
static void Main(string[] args)
{
using (SqlConnection conn = new SqlConnection(#"Data Source = XXXXXX\XXXXX; Initial Catalog = Test; Integrated Security = SSPI"))
{
XEStore store = new XEStore(new SqlStoreConnection(conn));
string sessionName = "abc";
if (store.Sessions[sessionName] != null)
{
Console.WriteLine("dropping existing session");
store.Sessions[sessionName].Drop();
}
Session s = store.CreateSession(sessionName);
s.MaxMemory = 4096;
s.MaxDispatchLatency = 30;
s.EventRetentionMode = Session.EventRetentionModeEnum.AllowMultipleEventLoss;
Event rpc = s.AddEvent("rpc_completed");
rpc.AddAction("username");
rpc.AddAction("database_name");
rpc.AddAction("sql_text");
rpc.PredicateExpression = #"sqlserver.username NOT LIKE '%testuser'";
s.Create();
s.Start();
int i = 0;
while (i < 15000)
{
s.Refresh();
foreach (var prop in rpc.Actions)
{
Console.WriteLine(prop.Description);
Console.WriteLine(prop.KeyChain);
Console.WriteLine(prop.IdentityKey);
Console.WriteLine(prop.Metadata);
Console.WriteLine(prop.ModuleID);
Console.WriteLine(prop.Name);
Console.WriteLine(prop.PackageName);
Console.WriteLine(prop.Parent);
Console.WriteLine(prop.Properties);
Console.WriteLine(prop.State);
Console.WriteLine(prop.Urn);
}
Thread.Sleep(1000);
}
}
}
}

How to trigger and find status of sql job through c#? [duplicate]

I need to create an application for monitoring SQL Server 2000 Agent Job status and info when Job occur same as show on Windows application event log. Now I connect to the database already via a connection string, but I don't know how to get the status and info from Job.
I need to show status and info on Textbox.
What do you suggestion how to do.
Developer tools :
MS SQL Sever 2000 SP4
MS Visual Studio 2008 (C#)
I am a rookie programmer.
i can do this already...
i select form table "Sysjobserver" in database "msdb" for read status, date, time of job that i want.
use this code
public void GetJobsAndStatus()
{
string sqlJobQuery = "select j.job_id, j.name, j.enabled, jh.run_status," +
" js.last_outcome_message, jh.run_date, jh.step_name, jh.run_time" +
" from sysjobs j left join sysjobhistory jh on (j.job_id = jh.job_id)" +
" left join sysjobservers js on (j.job_id = js.job_id)" +
" where jh.run_date = (select Max(run_date) from sysjobhistory)" +
" and jh.run_time = (select Max(run_time) from sysjobhistory)";
// create SQL connection and set up SQL Command for query
using (SqlConnection _con = new SqlConnection("server=10.15.13.70;database=msdb;user id=sa;pwd="))
using (SqlCommand _cmd = new SqlCommand(sqlJobQuery, _con))
{
try
{
// open connection
_con.Open();
SqlConnection.ClearPool(_con);
// create SQL Data Reader and grab data
using (SqlDataReader rdr = _cmd.ExecuteReader())
{
// as long as we get information from the reader
while (rdr.Read())
{
Guid jobID = rdr.GetGuid(0); // read Job_id
string jobName = rdr.GetString(1); // read Job name
byte jobEnabled = rdr.GetByte(2); // read Job enabled flag
int jobStatus = rdr.GetInt32(3); // read last_run_outcome from sysjobserver
string jobMessage = rdr.GetString(4); // read Message from sysjobserver
int jobRunDate = rdr.GetInt32(5); // read run_date from sysjobhistory
string jobStepName = rdr.GetString(6); // read StepName from sysjobhistory
int jobRunTime = rdr.GetInt32(7); // read run_time from sysjobhistory
String[] lviData = new String[] // ตัวแปรอะเรย์ชื่อ lviData
{
jobID.ToString(),
jobName.ToString(),
jobStepName.ToString(),
jobMessage.ToString(),
jobStatus.ToString(),
jobRunDate.ToString(),
jobRunTime.ToString(),
//jobEnabled.ToString(),
};
newData = lviData;
DisplayList(); // for display data on datagridview
}
rdr.Close();
}
}
thank you for everybody help very much. :-D
SQL stored procedures of queries don't give you any system data unless you have db_owner rights on the msdb system database, at lease in SQL Server 2008. Therefore mentioned methods normally don't work for applications where you want to show or manage jobs. However SMO namespace provides you with managed code solution for many SQL Server management features, including the SQL Server Agent functions that only require SQLServerAgent* permissions that you normally could get sorted for your application user. A good intro of using SMO classes to work with jobs is given here:
http://www.codeproject.com/Tips/367470/Manage-SQL-Server-Agent-Jobs-using-Csharp
I work on a similar task now and whilst SQL queries give me access denied, with C# code and Microsoft.SqlServer.Management.Smo.Agent namespace I just listed all jobs with this code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo.Agent;
namespace SmoTest
{
class Program
{
static readonly string SqlServer = #"SQL01\SQL01";
static void Main(string[] args)
{
ServerConnection conn = new ServerConnection(SqlServer);
Server server = new Server(conn);
JobCollection jobs = server.JobServer.Jobs;
foreach (Job job in jobs)
{
Console.WriteLine(job.Name);
}
}
}
}
This should be a good starting point to find out how to find your SQL Agent jobs using T-SQL:
View (and disable) SQL Agent Jobs with TSQL
The script will list out all your jobs on your database, and when they will be run next and so forth.
Using the job_name, you should also be able to find out details about your jobs using the SQL Server Agent Stored Procedures in the msdb database on your server.
On SQL Server 2005 and above, you can use the system stored procedure msdb.dbo.sp_help_job to get information, including status, about SQL Server Agent Jobs. You can read more about sp_help_job at http://msdn.microsoft.com/en-us/library/ms186722(v=SQL.90).aspx.
Here is the sample code to do this from C#.
private Dictionary<int, string> ExecutionStatusDictionary = new Dictionary<int, string>()
{
{0, "Not idle or suspended"},
{1, "Executing"},
{2, "Waiting for thread"},
{3, "Between retries"},
{4, "Idle"},
{5, "Suspended"},
{7, "Performing completion actions"}
};
public string GetStatus()
{
SqlConnection msdbConnection = new SqlConnection("Data Source=SERVERNAME;Initial Catalog=msdb;Integrated Security=SSPI");
System.Text.StringBuilder resultBuilder = new System.Text.StringBuilder();
try
{
msdbConnection.Open();
SqlCommand jobStatusCommand = msdbConnection.CreateCommand();
jobStatusCommand.CommandType = CommandType.StoredProcedure;
jobStatusCommand.CommandText = "sp_help_job";
SqlParameter jobName = jobStatusCommand.Parameters.Add("#job_name", SqlDbType.VarChar);
jobName.Direction = ParameterDirection.Input;
jobName.Value = "LoadRegions";
SqlParameter jobAspect = jobStatusCommand.Parameters.Add("#job_aspect", SqlDbType.VarChar);
jobAspect.Direction = ParameterDirection.Input;
jobAspect.Value = "JOB";
SqlDataReader jobStatusReader = jobStatusCommand.ExecuteReader();
while (jobStatusReader.Read())
{
resultBuilder.Append(string.Format("{0} {1}",
jobStatusReader["name"].ToString(),
ExecutionStatusDictionary[(int)jobStatusReader["current_execution_status"]]
));
}
jobStatusReader.Close();
}
finally
{
msdbConnection.Close();
}
return resultBuilder.ToString();
}
You can get a list of all server jobs using this SELECT:
SELECT [name] FROM msdb.dbo.sysjobs
If you'd like to get a list of currently running jobs and their information, I would recommend writing a stored procedure in SQL which your application calls. There's a good demonstration here you could use...
http://feodorgeorgiev.com/blog/2010/03/how-to-query-currently-running-sql-server-agent-jobs/
Good luck!
For my use case, I specifically needed to know when the job was finished running, and whether or not it succeeded. Here is my code to do that:
using System;
using System.Data;
using System.Data.SqlClient;
namespace LaunchJobAndWaitTillDone
{
class Program
{
const string connectionString = "Data Source=YOURSERVERNAMEHERE;Initial Catalog=msdb;Integrated Security=SSPI";
const string jobName = "YOURJOBNAMEHERE";
static readonly TimeSpan waitFor = TimeSpan.FromSeconds(1.0);
enum JobExecutionResult
{
Succeeded,
FailedToStart,
FailedAfterStart,
Unknown
}
static void Main(string[] args)
{
var instance = new Program();
JobExecutionResult jobResult = instance.RunJob(jobName);
switch (jobResult)
{
case JobExecutionResult.Succeeded:
Console.WriteLine($"SQL Server Agent job, '{jobName}', ran successfully to completion.");
break;
case JobExecutionResult.FailedToStart:
Console.WriteLine($"SQL Server Agent job, '{jobName}', failed to start.");
break;
case JobExecutionResult.FailedAfterStart:
Console.WriteLine($"SQL Server Agent job, '{jobName}', started successfully, but encountered an error.");
break;
default:
Console.WriteLine($"Unknown result from attempting to run SQL Server Agent job, '{jobName}'.");
break;
}
Console.ReadLine();
return;
}
JobExecutionResult RunJob(string jobName)
{
int jobResult;
using (var jobConnection = new SqlConnection(connectionString))
{
SqlCommand jobCommand;
SqlParameter jobReturnValue;
SqlParameter jobParameter;
jobCommand = new SqlCommand("sp_start_job", jobConnection);
jobCommand.CommandType = CommandType.StoredProcedure;
jobReturnValue = new SqlParameter("#RETURN_VALUE", SqlDbType.Int);
jobReturnValue.Direction = ParameterDirection.ReturnValue;
jobCommand.Parameters.Add(jobReturnValue);
jobParameter = new SqlParameter("#job_name", SqlDbType.VarChar);
jobParameter.Direction = ParameterDirection.Input;
jobCommand.Parameters.Add(jobParameter);
jobParameter.Value = jobName;
jobConnection.Open();
try
{
jobCommand.ExecuteNonQuery();
jobResult = (Int32)jobCommand.Parameters["#RETURN_VALUE"].Value;
}
catch (SqlException)
{
jobResult = -1;
}
}
switch (jobResult)
{
case 0:
break;
default:
return JobExecutionResult.FailedToStart;
}
while (true)
{
using (var jobConnection2 = new SqlConnection(connectionString))
{
SqlCommand jobCommand2 = new SqlCommand("sp_help_jobactivity", jobConnection2);
jobCommand2.CommandType = CommandType.StoredProcedure;
SqlParameter jobReturnValue2 = new SqlParameter("#RETURN_VALUE", SqlDbType.Int);
jobReturnValue2.Direction = ParameterDirection.ReturnValue;
jobCommand2.Parameters.Add(jobReturnValue2);
SqlParameter jobParameter2 = new SqlParameter("#job_name", SqlDbType.VarChar);
jobParameter2.Direction = ParameterDirection.Input;
jobCommand2.Parameters.Add(jobParameter2);
jobParameter2.Value = jobName;
jobConnection2.Open();
SqlDataReader rdr = jobCommand2.ExecuteReader();
while (rdr.Read())
{
object msg = rdr["message"];
object run_status = rdr["run_status"];
if (!DBNull.Value.Equals(msg))
{
var message = msg as string;
var runStatus = run_status as Int32?;
if (message != null && message.StartsWith("The job succeeded")
&& runStatus.HasValue && runStatus.Value == 1)
{
return JobExecutionResult.Succeeded;
}
else if (message != null && message.StartsWith("The job failed"))
{
return JobExecutionResult.FailedAfterStart;
}
else if (runStatus.HasValue && runStatus.Value == 1)
{
return JobExecutionResult.Unknown;
}
}
}
}
System.Threading.Thread.Sleep(waitFor);
}
}
}
}
Note that you may need database/server owner permissions or something like that for this code to work.

linqToSQL datetime get latest from table

Hi I trying to get the max timedate from a table using LinqToSQL. I already asked a similar question, but was trying to do something a bit more specific, and no one was able to help. This time, i would not mind using any solution, short of an Execute SQL task in another part of the SSIS package. This is my whole code. I was trying just to get the Identity column and it wasnt even working, so ignore the ToString please if it seems out of place. I just want to get the latest CREATED_TIMESTAMP please
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.IO;
using System.Linq;
using System.Data.SqlClient;
using System.Linq.Expressions;
using System.Collections;
using System.Collections.Generic;
using System.Data.Linq.Mapping;
using System.Data.Linq;
namespace ST_663004ffff194a14b84e2291578ada33.csproj
{
[System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
#region VSTA generated code
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
//Strings for connections
string iFileName;
string oFileName;
string RW;
public void Main()
{
Dts.Variables["latestTableRow"].Value = getLatest();
MessageBox.Show(getLatest());
Dts.TaskResult = (int)ScriptResults.Success;
}// End Main
public string getLatest()
{
string result = "";
////temp dummy/defaul date is two days ago
//DateTime result = new DateTime();
//result = DateTime.Now.AddDays(-2);
try
{
//get the data connection string from the connection manager
RW = (string)Dts.Connections["ReportingWarehouse"].ConnectionString;
//Remove the Provider, Auto Translate, and Application
//as it is not a parameter for the DataContext constructor
RW = RW.Remove(RW.IndexOf("Provider=SQLNCLI10.1;"), "Provider=SQLNCLI10.1;".Length);
RW = RW.Remove(RW.IndexOf("Auto Translate=False;"), "Provider=SQLNCLI10.1;".Length);
RW = RW.Remove(RW.IndexOf("Application"),RW.Length - RW.IndexOf("Application"));
MessageBox.Show(RW);
//get the last insertion date from the SSASLoging table
using (DataContext RWData = new DataContext(RW))
{
Table<SSASLogging> records = RWData.GetTable<SSASLogging>();
var rs = (from r in records
orderby r.TimeStamp descending
select r).Max();
result = rs.Errorval.ToString();
}
MessageBox.Show(result);
}
catch (Exception e)
{
MessageBox.Show("Exception in retreiving latest time: " + e.Message + "/n"
+ e.StackTrace);
}
return result;
}
}//end partial class
[Table(Name = "SSASLogging")]
public class SSASLogging
{
private DateTime timeStamp;
[Column(Name = "CREATED_TIMESTAMP")]
public DateTime TimeStamp
{
get { return this.timeStamp; }
private set { ;}
}
}//End SSASLogging
}
Ok this works
using (DataContext RWData = new DataContext(RW))
{
Table<SSASLogging> records = RWData.GetTable<SSASLogging>();
var rs = (from r in records
select r).Max(r => r.TimeStamp);
result = rs;
}

How to use ormlite with SQL Server and Mars?

ServiceStack aficionados, hello!
We are legion (I hope so), so please help a brother out :)
I am trying to populate two collections with one SQL Server 2008 stored procedure call that return two resultsets.
I have "MultipleActiveResultSets=True" in my connection string but I am still getting this error:
'r.NextResult()' threw an exception of type
'System.InvalidOperationException'
Here is my code:
IList<ProjectMember> projectMembers = null;
IList<Project> projects = DbFactory.Run(dbCnx =>
{
using (var dbCmd = dbCnx.CreateCommand())
{
dbCmd.CommandType = CommandType.StoredProcedure;
dbCmd.CommandText = "mySchema.myStoredProc";
dbCmd.Parameters.Add(new SqlParameter("#categoryId", categoryId));
using (profiler.Step("ProjectService.myStoredProc"))
{
var r = dbCmd.ExecuteReader();
projectMembers = r.ConvertToList<ProjectMember>();
return r.NextResult() ? r.ConvertToList<Project>() : null;
}
}
});
Is this possible? If so, can someone please show me an example on how to do that?
Thanks,
Samir
I've found a way but I had to replace ormLite with Dapper:
using(var cnx = DbFactory.CreateConnection(Global.ConnectionString))
{
using (var multi = cnx.QueryMultiple("mySchema.myStoredProc", new { communityId, categoryId }, commandType: CommandType.StoredProcedure))
{
var projectMembers = multi.Read<ProjectMember>().ToList();
var projects = multi.Read<Project>().ToList();
BindProjectMembers(projects, projectMembers);
return projects;
}
}
It works perfectly and is twice as fast (from 40 ms to 20 ms) than before the MARS amelioration.

How to monitor SQL Server Agent Job info in C#

I need to create an application for monitoring SQL Server 2000 Agent Job status and info when Job occur same as show on Windows application event log. Now I connect to the database already via a connection string, but I don't know how to get the status and info from Job.
I need to show status and info on Textbox.
What do you suggestion how to do.
Developer tools :
MS SQL Sever 2000 SP4
MS Visual Studio 2008 (C#)
I am a rookie programmer.
i can do this already...
i select form table "Sysjobserver" in database "msdb" for read status, date, time of job that i want.
use this code
public void GetJobsAndStatus()
{
string sqlJobQuery = "select j.job_id, j.name, j.enabled, jh.run_status," +
" js.last_outcome_message, jh.run_date, jh.step_name, jh.run_time" +
" from sysjobs j left join sysjobhistory jh on (j.job_id = jh.job_id)" +
" left join sysjobservers js on (j.job_id = js.job_id)" +
" where jh.run_date = (select Max(run_date) from sysjobhistory)" +
" and jh.run_time = (select Max(run_time) from sysjobhistory)";
// create SQL connection and set up SQL Command for query
using (SqlConnection _con = new SqlConnection("server=10.15.13.70;database=msdb;user id=sa;pwd="))
using (SqlCommand _cmd = new SqlCommand(sqlJobQuery, _con))
{
try
{
// open connection
_con.Open();
SqlConnection.ClearPool(_con);
// create SQL Data Reader and grab data
using (SqlDataReader rdr = _cmd.ExecuteReader())
{
// as long as we get information from the reader
while (rdr.Read())
{
Guid jobID = rdr.GetGuid(0); // read Job_id
string jobName = rdr.GetString(1); // read Job name
byte jobEnabled = rdr.GetByte(2); // read Job enabled flag
int jobStatus = rdr.GetInt32(3); // read last_run_outcome from sysjobserver
string jobMessage = rdr.GetString(4); // read Message from sysjobserver
int jobRunDate = rdr.GetInt32(5); // read run_date from sysjobhistory
string jobStepName = rdr.GetString(6); // read StepName from sysjobhistory
int jobRunTime = rdr.GetInt32(7); // read run_time from sysjobhistory
String[] lviData = new String[] // ตัวแปรอะเรย์ชื่อ lviData
{
jobID.ToString(),
jobName.ToString(),
jobStepName.ToString(),
jobMessage.ToString(),
jobStatus.ToString(),
jobRunDate.ToString(),
jobRunTime.ToString(),
//jobEnabled.ToString(),
};
newData = lviData;
DisplayList(); // for display data on datagridview
}
rdr.Close();
}
}
thank you for everybody help very much. :-D
SQL stored procedures of queries don't give you any system data unless you have db_owner rights on the msdb system database, at lease in SQL Server 2008. Therefore mentioned methods normally don't work for applications where you want to show or manage jobs. However SMO namespace provides you with managed code solution for many SQL Server management features, including the SQL Server Agent functions that only require SQLServerAgent* permissions that you normally could get sorted for your application user. A good intro of using SMO classes to work with jobs is given here:
http://www.codeproject.com/Tips/367470/Manage-SQL-Server-Agent-Jobs-using-Csharp
I work on a similar task now and whilst SQL queries give me access denied, with C# code and Microsoft.SqlServer.Management.Smo.Agent namespace I just listed all jobs with this code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo.Agent;
namespace SmoTest
{
class Program
{
static readonly string SqlServer = #"SQL01\SQL01";
static void Main(string[] args)
{
ServerConnection conn = new ServerConnection(SqlServer);
Server server = new Server(conn);
JobCollection jobs = server.JobServer.Jobs;
foreach (Job job in jobs)
{
Console.WriteLine(job.Name);
}
}
}
}
This should be a good starting point to find out how to find your SQL Agent jobs using T-SQL:
View (and disable) SQL Agent Jobs with TSQL
The script will list out all your jobs on your database, and when they will be run next and so forth.
Using the job_name, you should also be able to find out details about your jobs using the SQL Server Agent Stored Procedures in the msdb database on your server.
On SQL Server 2005 and above, you can use the system stored procedure msdb.dbo.sp_help_job to get information, including status, about SQL Server Agent Jobs. You can read more about sp_help_job at http://msdn.microsoft.com/en-us/library/ms186722(v=SQL.90).aspx.
Here is the sample code to do this from C#.
private Dictionary<int, string> ExecutionStatusDictionary = new Dictionary<int, string>()
{
{0, "Not idle or suspended"},
{1, "Executing"},
{2, "Waiting for thread"},
{3, "Between retries"},
{4, "Idle"},
{5, "Suspended"},
{7, "Performing completion actions"}
};
public string GetStatus()
{
SqlConnection msdbConnection = new SqlConnection("Data Source=SERVERNAME;Initial Catalog=msdb;Integrated Security=SSPI");
System.Text.StringBuilder resultBuilder = new System.Text.StringBuilder();
try
{
msdbConnection.Open();
SqlCommand jobStatusCommand = msdbConnection.CreateCommand();
jobStatusCommand.CommandType = CommandType.StoredProcedure;
jobStatusCommand.CommandText = "sp_help_job";
SqlParameter jobName = jobStatusCommand.Parameters.Add("#job_name", SqlDbType.VarChar);
jobName.Direction = ParameterDirection.Input;
jobName.Value = "LoadRegions";
SqlParameter jobAspect = jobStatusCommand.Parameters.Add("#job_aspect", SqlDbType.VarChar);
jobAspect.Direction = ParameterDirection.Input;
jobAspect.Value = "JOB";
SqlDataReader jobStatusReader = jobStatusCommand.ExecuteReader();
while (jobStatusReader.Read())
{
resultBuilder.Append(string.Format("{0} {1}",
jobStatusReader["name"].ToString(),
ExecutionStatusDictionary[(int)jobStatusReader["current_execution_status"]]
));
}
jobStatusReader.Close();
}
finally
{
msdbConnection.Close();
}
return resultBuilder.ToString();
}
You can get a list of all server jobs using this SELECT:
SELECT [name] FROM msdb.dbo.sysjobs
If you'd like to get a list of currently running jobs and their information, I would recommend writing a stored procedure in SQL which your application calls. There's a good demonstration here you could use...
http://feodorgeorgiev.com/blog/2010/03/how-to-query-currently-running-sql-server-agent-jobs/
Good luck!
For my use case, I specifically needed to know when the job was finished running, and whether or not it succeeded. Here is my code to do that:
using System;
using System.Data;
using System.Data.SqlClient;
namespace LaunchJobAndWaitTillDone
{
class Program
{
const string connectionString = "Data Source=YOURSERVERNAMEHERE;Initial Catalog=msdb;Integrated Security=SSPI";
const string jobName = "YOURJOBNAMEHERE";
static readonly TimeSpan waitFor = TimeSpan.FromSeconds(1.0);
enum JobExecutionResult
{
Succeeded,
FailedToStart,
FailedAfterStart,
Unknown
}
static void Main(string[] args)
{
var instance = new Program();
JobExecutionResult jobResult = instance.RunJob(jobName);
switch (jobResult)
{
case JobExecutionResult.Succeeded:
Console.WriteLine($"SQL Server Agent job, '{jobName}', ran successfully to completion.");
break;
case JobExecutionResult.FailedToStart:
Console.WriteLine($"SQL Server Agent job, '{jobName}', failed to start.");
break;
case JobExecutionResult.FailedAfterStart:
Console.WriteLine($"SQL Server Agent job, '{jobName}', started successfully, but encountered an error.");
break;
default:
Console.WriteLine($"Unknown result from attempting to run SQL Server Agent job, '{jobName}'.");
break;
}
Console.ReadLine();
return;
}
JobExecutionResult RunJob(string jobName)
{
int jobResult;
using (var jobConnection = new SqlConnection(connectionString))
{
SqlCommand jobCommand;
SqlParameter jobReturnValue;
SqlParameter jobParameter;
jobCommand = new SqlCommand("sp_start_job", jobConnection);
jobCommand.CommandType = CommandType.StoredProcedure;
jobReturnValue = new SqlParameter("#RETURN_VALUE", SqlDbType.Int);
jobReturnValue.Direction = ParameterDirection.ReturnValue;
jobCommand.Parameters.Add(jobReturnValue);
jobParameter = new SqlParameter("#job_name", SqlDbType.VarChar);
jobParameter.Direction = ParameterDirection.Input;
jobCommand.Parameters.Add(jobParameter);
jobParameter.Value = jobName;
jobConnection.Open();
try
{
jobCommand.ExecuteNonQuery();
jobResult = (Int32)jobCommand.Parameters["#RETURN_VALUE"].Value;
}
catch (SqlException)
{
jobResult = -1;
}
}
switch (jobResult)
{
case 0:
break;
default:
return JobExecutionResult.FailedToStart;
}
while (true)
{
using (var jobConnection2 = new SqlConnection(connectionString))
{
SqlCommand jobCommand2 = new SqlCommand("sp_help_jobactivity", jobConnection2);
jobCommand2.CommandType = CommandType.StoredProcedure;
SqlParameter jobReturnValue2 = new SqlParameter("#RETURN_VALUE", SqlDbType.Int);
jobReturnValue2.Direction = ParameterDirection.ReturnValue;
jobCommand2.Parameters.Add(jobReturnValue2);
SqlParameter jobParameter2 = new SqlParameter("#job_name", SqlDbType.VarChar);
jobParameter2.Direction = ParameterDirection.Input;
jobCommand2.Parameters.Add(jobParameter2);
jobParameter2.Value = jobName;
jobConnection2.Open();
SqlDataReader rdr = jobCommand2.ExecuteReader();
while (rdr.Read())
{
object msg = rdr["message"];
object run_status = rdr["run_status"];
if (!DBNull.Value.Equals(msg))
{
var message = msg as string;
var runStatus = run_status as Int32?;
if (message != null && message.StartsWith("The job succeeded")
&& runStatus.HasValue && runStatus.Value == 1)
{
return JobExecutionResult.Succeeded;
}
else if (message != null && message.StartsWith("The job failed"))
{
return JobExecutionResult.FailedAfterStart;
}
else if (runStatus.HasValue && runStatus.Value == 1)
{
return JobExecutionResult.Unknown;
}
}
}
}
System.Threading.Thread.Sleep(waitFor);
}
}
}
}
Note that you may need database/server owner permissions or something like that for this code to work.

Categories

Resources