开发者

What is wrong with my program logic

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜