希望我能在这里得到一些帮助。
在DEV服务器上,我在Visual Studio 2013社区中创建了一个C#windows服务。我在调试模式下测试了它: 在Main()
#if DEBUG
...run debug code...
#else
...run service code...
#endif
在调试模式下,它运行得很好。然后,我添加了一个安装程序类,并在 相同的 服务器上成功安装了该服务,并在“服务”窗口中启动了该服务。但是,它没有做任何事情。我检查了事件日志并看到了以下错误消息:
Application: SharenetIFF.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.NullReferenceException
at SharenetIFF.RunValues.GetRunValues()
at SharenetIFF.SearchFiles.LookforIFFFiles(Int32)
at SharenetIFF.Program.DoThis()
at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Threading.ThreadHelper.ThreadStart()
以下是RunValues中的代码:
class RunValues
{
public int id { get; set; }
public int runTimeSpan { get; set; }
public int numberOfRunTime { get; set; }
private SqlConnection myCon = new SqlConnection();
public List<int> GetRunValues()
{
List<int> values = null;
string destPath = "";
try
{
string mySQL = "select RunFreq, RunTimes from IFFRunValues";
myCon.ConnectionString = ConfigurationManager.ConnectionStrings["DatabaseConn"].ConnectionString;
myCon.Open();
SqlCommand myCmd = new SqlCommand(mySQL, myCon);
SqlDataReader runValuesReader = myCmd.ExecuteReader();
if (runValuesReader.HasRows)
{
while (runValuesReader.Read())
{
runTimeSpan = Convert.ToInt16(runValuesReader["RunFreq"]);
numberOfRunTime = Convert.ToInt16(runValuesReader["RunTimes"]);
}
values = new List<int>();
values.Add(runTimeSpan);
values.Add(numberOfRunTime);
}
runValuesReader.Close();
myCon.Close();
runValuesReader.Dispose();
myCmd.Dispose();
myCon.Dispose();
}
catch (Exception ex)
{
destPath = Path.Combine("C:\\", "error_log.txt");
File.AppendAllText(destPath, ex.Message);
values.Clear();
}
return values;
}
}
我认为它在连接字符串上失败了,主要是因为这里没有别的东西。但不知道为什么。所有代码都在try / catch块中,那么如何处理未处理的异常呢?如果服务发布到开发的同一台开发机器上,如果在visual studio外部运行,服务是否需要不同的权限?
答案 0 :(得分:0)
这最初是作为评论,但是太长了,所以......
该方法应该做什么并不完全清楚。一方面,您填充实例的属性。另一方面,您返回int
的列表,但是您将值转换为Int16
(short
}而不是Int32
。在循环之后填充该列表,这意味着您只获得select语句返回的最后一个值,没有order by子句意味着行以任意顺序返回,并且您不使用Id
属性。
另外,请注意Steve关于将文件直接保存到C:\
的评论。
在我们甚至触及您使用SQLConnection
的字段而不是using
语句中的局部变量这一事实之前,这将确保它将被关闭并且一旦你完成它就被处置掉了,或者你只将一切都放在try
块内,这意味着如果你的代码到达那里之前有一个例外,那么什么都不会被处理掉,或者表中的列是数据库可能是可空的,因此如果读者包含Convert.ToInt
而不是实际值,则DBNull.Value
可能会失败。
话虽如此,这是您当前代码的改进版本。我只修改了它应该正确处理所有内容,安全地从dataReader获取值而不是抛出NullReferenceException
,但正如我所说,我不是很清楚你尝试用这种方法实现。
class RunValues
{
public int id { get; set; }
public int runTimeSpan { get; set; }
public int numberOfRunTime { get; set; }
public List<int> GetRunValues()
{
var values = new List<int>();
// I'm guessing it needs " where id = @id" here...
var mySQL = "select RunFreq, RunTimes from IFFRunValues";
using(var myCon = new SqlConnection(ConfigurationManager.ConnectionStrings["DatabaseConn"].ConnectionString))
{
using(var myCmd = new SqlCommand(mySQL, myCon))
{
try
{
myCon.Open();
SqlDataReader runValuesReader = myCmd.ExecuteReader();
if (runValuesReader.HasRows)
{
while (runValuesReader.Read())
{
runTimeSpan = runValuesReader.GetValueOrDefault<int>("RunFreq");
numberOfRunTime = runValuesReader.GetValueOrDefault<int>("RunTimes");
values.Add(runTimeSpan);
values.Add(numberOfRunTime);
}
}
}
catch (Exception ex)
{
var destPath = Path.Combine("C:\\", "error_log.txt");
File.AppendAllText(destPath, ex.Message);
values.Clear();
}
}
}
return values;
}
}
GetValueOrDefault<T>
是我一直在使用的扩展方法,我甚至不记得我第一次遇到它的地方 - 这是包含它的类:
/// <summary>
/// Provides extension methods for IDataReader.
/// </summary>
public static class IDataReaderExtensions
{
/// <summary>
/// Gets the value of type T from the column specified by the index parameter, or default(T) if it's null.
/// </summary>
/// <typeparam name="T">The type of the value to get.</typeparam>
/// <param name="reader">An instance of a class implementing IDataReader.</param>
/// <param name="index">The index of the column from where to get the value.</param>
/// <returns>The value of type T from the specified column, default(T) if null.</returns>
public static T GetValueOrDefault<T>(this IDataReader reader, int index)
{
return (Convert.IsDBNull(reader[index])) ? default(T) : (T)reader.GetValue(index);
}
/// <summary>
/// Gets the value of type T from the column specified by the name parameter, or default(T) if it's null.
/// </summary>
/// <typeparam name="T">The type of the value to get.</typeparam>
/// <param name="reader">An instance of a class implementing IDataReader.</param>
/// <param name="name">The name of the column from where to get the value.</param>
/// <returns>The value of type T from the specified column, default(T) if null.</returns>
public static T GetValueOrDefault<T>(this IDataReader reader, string name)
{
return reader.GetValueOrDefault<T>(reader.GetOrdinal(name));
}
}