This thread is a continuation of Is there a reason to check for null inside multiple using clausule in c#?
I've noticed that resharper lets me define using without opening any opening/closing bracket like in the method below (but then i can't use defined vars later on if the brackets ain't there, other then the one that is used exactly beneath defined using):
public static string sqlGetDatabaseRows() {
string varRows = "";
const string preparedCommand = #"
SELECT SUM(row_count) AS 'Rows'
FROM sys.dm_db_partition_stats
WHERE index_id IN (0,1)
AND OBJECTPROPERTY([object_id], 'IsMsShipped') = 0;";
using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP))
using (var sqlQuery = new SqlCommand(preparedCommand, varConnection))
using (var sqlQueryResult = sqlQuery.ExecuteReader())
if (sqlQueryResult != null) {
while (sqlQueryResult.Read()) {
varRows = sqlQueryResult["Rows"].ToString();
}
sqlQueryResult.Close();
}
return varRows;
}
Is it good? Or should i use it like this?
public static string sqlGetDatabaseRows() {
string varRows = "";
const string preparedCommand = #"
SELECT SUM(row_count) AS 'Rows'
FROM sys.dm_db_partition_stats
WHERE index_id IN (0,1)
AND OBJECTPROPERTY([object_id], 'IsMsShipped') = 0;";
using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP)) {
using (var sqlQuery = new SqlCommand(preparedCommand, varConnection))
using (var sqlQueryResult = sqlQuery.ExecuteReader())
if (sqlQueryResult != null) {
while (sqlQueryResult.Read()) {
varRows = sqlQueryResult["Rows"].ToString();
}
sqlQueryResult.Close();
}
varConnection.Close();
}
return varRows;
}
sqlConnectOneTime looks like this:
public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails) {
SqlConnection sqlConnection = new SqlConnection(varSqlConnectionDetails);
sqlConnect(sqlConnection);
if (sqlConnection.State == ConnectionState.Open) {
return sqlConnection;
}
return null;
}
My questions are:
Should I be closing varConnection by using varConnection.Close() and sqlQueryResult.Close(); in the end? (but this enforces use of brackets) or will the connection close itself when using is done.
Should i be checking for NULL for varConnection since it's possible it will return null (on the other hand resharper doesn't complain here).
Is there some better approach i could use for defining sqlConnectOneTime ? Like when the connection fails to open it should return ConnectionState.Closed instead of null?
Also just on a note i open up new connection every time i execute new query / update / insert since i am using threading and it was the smartest idea i could come up at that very moment. Feel free to suggest better one :-)
I am asking about all this since i want to better understand whole process and stop making silly mistakes so be gentle with me.
MadBoy
Edit: modified question if varConnection.Close() and sqlQueryResult.Close() are nessecary if using is used.
Close() is called by the Dispose() method, so as long as you are using "using" properly you don't need to call Close() explicitly.
If it's possible for a NULL to be returned, you should check for it. I would advise that if you control the code that gets the sql connection, you strongly consider throwing an exception rather than returning NULL. Otherwise other developers may run into the same sorts of problems. Failure to open a SQL connection that is required seems to me to be a valid exceptional case. If necessary, you can always include a TryConnectOneTime for when a developer wants to avoid exception handling.
Also, another style note - I would advise properly bracing your using statements in case a stray extra line is added and an unexpected error occurs. Style-wise, I usually don't tend to indent using statements when I have multiple statements together, but that's all down to personal preference.
It's safe to use it like in the first example. using closes the reader, command and connection objects and even checks for null values (so you don't get a NullReferenceException if varConnection is null)
Related
I have a problem. I have to save figures to txt ( its not important what it means). I would like to have space between numbers.
When I try to save it without spaces it works good
This is my code without space
if (x_dolny > x1_sqr && x_dolny < x2_sqr)
{
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.Write("1");
}
}
else if (y_prawy < y1_sqr && y_prawy > y2_sqr)
{
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.Write("1");
}
}
else if (delta >= 0.0)
{
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.Write("2");
}
}
else
{
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.Write("0");
}
}
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.WriteLine("New line");
}
And here is a screenshot outputdata.txt
and then I tried to add "\t"
So now I have
streamW.Write("1 \t");
streamW.Write("2 \t");
streamW.Write("0 \t");
but the file looks like this
I dont understand why it cuts my line and move to the next line...
Any ideas?
As #Sinatr mentioned in the comments, this could just be a word-wrap issue in your text editor.
Off topic though, this code could really use some refactoring to make it simpler and much easier to read and understand.
using (var streamWriter = new StreamWriter(#"C:\Users\Desktop\outputdata.txt", true))
{
string message = "0";
if (MessageIs1(x_dolny, x1_sqr, x2_sqr, y_prawy, y1_sqr, y2_sqr))
message = "1";
else if (delta >= 0.0)
message = "2";
streamWriter.Write(message);
streamWriter.WriteLine("New line");
}
// ...
private static bool MessageIs1(int x_dolny, int x1_sqr, int x2_sqr,
int y_prawy, int y1_sqr, int y2_sqr)
{
return (x_dolny > x1_sqr && x_dolny < x2_sqr)
|| (y_prawy < y1_sqr && y_prawy > y2_sqr);
}
Here's some suggestions:
You reused the StreamWriter in every branch of your if statements and even after. Instead of typing the using statements several times, wrap it all in one using statement. Try to follow the DRY principle (Don't Repeat Yourself).
You can use var when the data type is obvious from the assignment (such as creating new objects).
Try to make your identifiers (variable names and method names) as clear and concise as possible. Others reading your code shouldn't have to look around a lot to figure out what your variables or methods are doing; it should be obvious just from the name. Avoid abbreviations because others may not know what the abbreviation stands for or may assume it means something else. I didn't know what your variables were for because I couldn't look at the full source, but I would definitely rename the following from my example above: x_dolny, x1_sqr, x2_sqr, y_prawy, y1_sqr, y2_sqr, MessageIs1.
Extract complex boolean logic into a method so it is easier to read and change if you or someone else needs to later.
Use verbatim string literals for file paths.
Try to adhere to the KISS Principle (Keep It Simple, Stupid) as much as possible. Most developers over-engineer. Simple code is easy to read, understand, maintain, and extend.
I have this code:
var a = 2;
I type using(...){} above declaration
Then I`m getting:
using(...)
{
}
var a = 2;
visual studio adds tab to a declaration. I want to prevent this, how I can achieve it ?
Edit: I added braces as I don`t want to have a inside using.
That is because the using statement executes codes whitin the scope the variable whitin the using exists. The correct syntax for using is:
using (var disposeMe = new DisposeMe())
{
// here you use the disposeMe object during its lifetime
var a = 2;
} // here disposeMe gets disposed.
With regards,
John
I have a task to poll application event log periodically to check for new entries and process them, later parsing them to an .evtx file.
This task is not a problem.
I am using a code like that:
using (var els = new EventLogSession())
{
string timeString = timestamp.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
string queryString = String.Format(
"<QueryList> <Query Id='0' Path='{0}'> <Select Path='{0}'> " +
"*[System[TimeCreated[#SystemTime>'{1}']]]</Select> </Query> </QueryList>",
logName, timeString);
var query = new EventLogQuery(logName, PathType.LogName, queryString) { Session = els };
var records = new List<EventRecord>();
using (var logReader = new EventLogReader(query))
{
EventRecord record;
while ((record = logReader.ReadEvent()) != null)
{
//log entries processed here
...
//finally export log messages to a file
els.ExportLogAndMessages(logName, PathType.LogName, queryString, fileName, true, CultureInfo.GetCultureInfo("en"));
}
}
}
Unfortunately I found out that after restarting my PC and starting application - EventLogReader always returns the same set of messages, even if I restart my application. That means - new messages do not appear in the results yielded by logReader.ReadEvent() method.
However - changing query string to a simple asterisk and passing it to EventLogQuery - resolves this situation, logReader returns all messages including new ones.
For now, I stick with "*" query string and filter old entries with code, but this seems to be not the best solution to me.
Is it a mistake in my query? Is it a mistake with my handling of EventLogSession or EventLogReader objects? Is it a known MS bug?
I know this is an old question, but it doesn't have an answer and I've been working in this area lately.
Possible issues with this code:
Use UTC time for your date, and
.ToString("o")
instead of
.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
Don't include any of the extraneous XML in the query string. You only need the query bit. So it should be:
string queryString = String.Format(
"*[System[TimeCreated[#SystemTime>'{0}']]]",
timeString);
Consider using an EventBookmark instead of constructing a complex query expression for date filtering. EventBookmarks were designed for that purpose. See How to create an EventBookmark when querying the event log for an example of using EventBookmark for a very similar kind of purpose.
Once you have an EventBookmark you simply use:
using (var logReader = new EventLogReader(query, EventBookmark))
to ensure that your reader starts at the entry after the previous bookmark.
My query seems to be stalling every so many passes through the query.
status_text.Text = "Check existing records...";
status_text.Refresh();
using (StreamReader reader = new StreamReader(df_text_filename))
{
using (StreamWriter writer = new StreamWriter(df_text_filename + "_temp"))
{
while ((product = reader.ReadLine()) != null)
{
if (product != _aff_svc.DFHeaderProd)
{
df_product = _product_factory.GetProductData(_vsi, product);
}
status_text.Text = "Checking for existing record of vendor record ID " + df_product.SKU;
status_text.Refresh();
if (_pctlr.GetBySKU(df_product.SKU) != null)
{
continue;
}
writer.WriteLine(product);
Application.DoEvents();
}
writer.Close();
}
reader.Close();
}
System.IO.File.Delete(df_text_filename);
System.IO.File.Move(df_text_filename + "_temp", df_text_filename);
The code quickly runs through the GetBySKU about 10 times, pauses for about a second or so, then quickly does another ten records. This occurs throughout my processes, not just with this particular query.
It also occurs whether or not I have the Application.DoEvents() fire.
The other problem is that it is not consistent. I can be working like this for a few hours, then all of a sudden, it will zip through the loop as intended (expected).
My SQL server is running on the same machine as the program.
I looked into dedicating resources to the server to mitigate this behavior, but have found nothing.
It looks as if you're program is parsing a text file for product info and then as it parses, in a while loop you're executing a couple SQL queries. It's almost always a bad idea to make SQL round trips inside a loop.
Instead, I would look into parsing the file, gathering all the product ideas, closing the file and then make one call to sql passing a/many TVPs (table valued parameters) to a sproc and return all the data you need from that sproc - possibly as many tables.
EDIT:
You mentioned in the comments that the file is very large with lots of processing. You could consider batching the SQL work in lets say something like 100?
Also, if you're SQL isn't tuned it would continually slow down as more data is written. There's not enough info in the question to analyze the indexes, query plans etc... but have a look at that as the data set grows.
I will work on a batch solution later, however, this works much faster than the previous code. No pauses at all.
List<Product> _prod_list = new List<Product>();
_prod_list = ProductDataFactory.GetProductListByVendor(vendor_name);
if (_prod_list.Count() > 0)
{
using (StreamReader reader = new StreamReader(df_text_filename))
{
using (StreamWriter writer = new StreamWriter(df_text_filename + "_temp"))
{
while ((product = reader.ReadLine()) != null)
{
if (product != _aff_svc.DFHeaderProd)
{
df_product = _product_factory.GetProductData(_vsi, product);
}
if (_prod_list.Find(o => o.SKU == df_product.SKU) != null)
{
continue;
}
writer.WriteLine(product);
}
writer.Close();
}
reader.Close();
}
System.IO.File.Delete(df_text_filename);
System.IO.File.Move(df_text_filename + "_temp", df_text_filename);
}
Just pulling a list of product objects and query it for existing records if there are any; if not, it skips the whole process of course. No need to hit the db in the loop either.
Thanks.
Please help me find the defect in my logic. I have two variables named "prev" and "next"...What i am basically doing is reading the data from my database every 5s and printing it out using Websync server if next and prev are NOT equal. I have two rows in my database . It looks like
ID
8
10
Here is the link to the code http://pastebin.com/Hb3eH2Qv
When i run my program, i get the result as
8 10 8 10
8 10
8 10 8 10
8 10
..... (so on)
But, the result should be just
8 10
I dont know how 8 10 8 10 appears. Data gets concatenated twice.
NOTE: You can just see the code in PublishLoop() function
private void PublishLoop()
{
String prev=String.Copy("");
String next=String.Copy("");
String ConnectionString = ConfigurationManager.ConnectionStrings["MyDbConn"].ToString();
SqlConnection connection = new SqlConnection(ConnectionString);
SqlCommand command = connection.CreateCommand();
command.CommandText = "select ID from Tab1";
command.Notification = null;
while (Running)
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
StreamWriter sw1 = new StreamWriter("C:\\Users\\Thothathri\\Desktop\\next.txt");
while ((reader.Read()))
{
//Response.Write(reader[0].ToString());
next = String.Concat(next,reader[0].ToString());
sw1.WriteLine(next);
}
sw1.Close();
if (!prev.Equals(next))
{
Publisher publisher = new Publisher(new PublisherArgs
{
DomainKey = "c80cb405-eb77-4574-9405-5ba51832f5e6",
DomainName="localhost"
});
Publication publication = publisher.Publish("/test", JSON.Serialize(next));
if (publication.Successful == true)
{
StreamWriter sw = new StreamWriter("C:\\Users\\Thothathri\\Desktop\\error123.txt");
sw.WriteLine("success");
sw.WriteLine(next);
sw.Close();
}
else
{
StreamWriter sw = new StreamWriter("C:\\Users\\Thothathri\\Desktop\\error123.txt");
sw.Write("failed");
sw.Close();
}
prev = String.Copy(next);
next = String.Copy("");
}
}
Thread.Sleep(5000);
}
}
Renuiz answered it in a comment, but it is because you're not clearing next.
So you build the string "8 10" in next, store it in prev. Next time you concat "8 10" with next, making "8 10 8 10". Which is different so you print it.
if (!prev.Equals(next))
{
....
prev = String.Copy(next);
next = String.Copy("");
}
This is the end of that loop. You should really be clearing next at the beginning of that loop.
Also you can just set the string
next = String.Empty;
I would declare next inside your while loop, as you don't need it in the greater scope, and I would call it current rather than next.
What is really wrong with your program logic - logic is not obvious. It is so obscure, that you can't understand where error is. So, my advise is following - if you can't find the error, try to simplify your code.
Currently your method has many responsibilities - it queries database, it dumps data to file, it publishes data somewhere and logs the results. And you stuck with all that stuff. If someone will need to change database query, or publishing logic - he will need to review all other stuff.
So, separate logic first:
private void PublishLoop()
{
string previousIDs = String.Empty;
int timeout = Int32.Parse(ConfigurationManager.AppSettings["publishTimeout"]);
while (Running)
{
string currentIDs = ConcatenateList(LoadIDs());
Dump(currentIDs);
if (!previousIDs.Equals(currentIDs))
{
try
{
Publish(currentIDs);
_log.Info("Published successfuly");
}
catch (PublicationException exception)
{
_log.Error("Publication failed");
}
previousIDs = currentIDs;
}
Thread.Sleep(timeout);
}
}
Well, I don't know much about your domain, so you probably can think about better names for variables and methods.
Here you have data access logic extracted to separate method (it's ok for first step of refactoring and for small applications). Keep in mind, that wrapping connection object into using block guarantee that connection will be closed in case of exception:
private IList<int> LoadIDs()
{
List<int> ids = new List<int>();
String connectionString = ConfigurationManager.ConnectionStrings["MyDbConn"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = "select ID from Tab1";
command.Notification = null;
connection.Open();
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
while ((reader.Read()))
ids.Add((int)reader["ID"]);
}
}
return ids;
}
Next - simple method for concatenating ids into one string:
private string ConcatenateList(IList<int> values)
{
return String.Join(" ", values.Select(value => value.ToString()).ToArray());
}
Dumping (mind, that file name moved to configuration file):
private void Dump(string ids)
{
using (StreamWriter writer = new StreamWriter(ConfigurationManager.AppSettings["dumpFilePath"]))
writer.WriteLine(ids);
}
And publishing logic:
private void Publish(string ids)
{
PublisherArgs args = new PublisherArgs
{
DomainKey = "c80cb405-eb77-4574-9405-5ba51832f5e6",
DomainName = "localhost"
};
Publisher publisher = new Publisher(args);
Publication publication = publisher.Publish("/test", JSON.Serialize(ids));
if (!publication.Successful)
throw new PublicationException();
}
I think that failures are exceptional and they not occur very often (so I decided to use exceptions for that case). But if it's something ordinary - you can simply use boolean method like TryPublish.
BTW you can use some logging library like log4net for logging successful and failure publishing. Or you can extract logging logic to separate method - this will make primary logic cleaner and easier to understand.
PS try to avoid comparison of boolean variables with true/false (publication.Successful == true) - you can occasionally assign value to your variable.