当我尝试转换时间戳时,为什么会出现超出范围的消息

时间:2014-12-26 16:23:40

标签: c# class console-application outofrangeexception

所以我有以下代码:

  

listOfUserLogs.Add(new Log                           {                               TimeStamp = Convert.ToDateTime(myReader [" TimeStamp"]),                               CheckpointId = Convert.ToInt32(myReader [" CheckpointId"])                           });

当我运行程序时,我得到了System.IndexOutOfRangeException {"TimeStamp"}。我不明白为什么会这样以及如何解决它。

注意:我编辑了帖子,这样您就可以看到整个代码,让我知道我错过了什么。

你可以在这里看到我的节目:

namespace Distance
{
    class Program
    {
        static void Main(string[] args)
        {
            string connectionString = GetConnectionString();


            using (SqlConnection sourceConnection =
                       new SqlConnection(connectionString))
            {
                sourceConnection.Open();

                SqlDataReader myReader = null;

                SqlCommand myCommand = new SqlCommand("SELECT User.Id , [Log].[TimeStamp] ,[Checkpoints].[Id] ,[Checkpoints].[Coordinates] FROM dbo.[Users] INNER JOIN dbo.[Log] ON [Log].[UserId] =[Users].[Id] INNER JOIN dbo.[Checkpoints] ON [Checkpoints].[Id] = [Log].[CheckpointId] ", sourceConnection);

                //SqlCommand myCommand = new SqlCommand("SELECT User.Id ,User.Name ,Checkpoint.Id ,Checkpoint.Coordinates , Log.TimeStamp FROM dbo.Users, INNER JOIN dbo.Log ON Log.UserId = User.Id, INNER JOIN dbo.Checkpoints ON Checkpoint.Id = Log.CheckpointId ;", sourceConnection);

                myReader = myCommand.ExecuteReader();
                var listOfUsers = new List<User>(); //get users from db
                //long countStart = System.Convert.ToInt32(myCommand.ExecuteScalar());
                var listOfCheckpoints = new List<Checkpoint>(); //get checkpoints from db
                var listOfUserLogs = new List<Log>();
                while (myReader.Read())
                {
                    listOfUsers.Add(new User
                    {
                       Id = Convert.ToInt32(myReader["Id"]),
                       Name = myReader["Name"].ToString(),
                       Coordinates = myReader["Coordinates"].ToString()
                    });

                    listOfCheckpoints.Add(new Checkpoint
                    {
                        Id = Convert.ToInt32(myReader["Id"]),
                        Coordinates = myReader["Coordinates"].ToString()
                    });

                    listOfUserLogs.Add(new Log
                    {
                        TimeStamp = Convert.ToDateTime(myReader["TimeStamp"]),
                        CheckpointId = Convert.ToInt32(myReader["CheckpointId"]),
                        UserId =Convert.ToInt32(myReader["UserId"])
                    });

                }


            StringBuilder sb = new StringBuilder();
            foreach (var user in listOfUsers)
            {
                string address = user.Coordinates;

                DateTime currentDate = new DateTime(2014, 8, 1);
                var dictionary = new Dictionary<string, double>();

                while (currentDate <= DateTime.Now)
                {
                    double dayUserDistance = 0.00;
                   // var listOfUserLogs = new List<Log>(); //Get logs where day == currentDate from db
                    var previousCoordinate = address;
                    foreach (var log in listOfUserLogs)
                    {

                        Checkpoint checkpoint = listOfCheckpoints.FirstOrDefault(x => x.Id == log.CheckpointId);


                        dayUserDistance += DistanceCalculator.GetDistance(previousCoordinate, checkpoint.Coordinates);
                        previousCoordinate = checkpoint.Coordinates;

                    }
                    dayUserDistance += DistanceCalculator.GetDistance(previousCoordinate, address);

                    dictionary.Add(currentDate.ToString("yyyy-MM-dd"), dayUserDistance);

                    currentDate = currentDate.AddDays(1);
                }

                sb.Append(user.Name + ";");
                foreach (KeyValuePair<string, double> keyValuePair in dictionary)
                {
                    sb.Append(keyValuePair.Value + ";");
                }
                sb.AppendLine();
            }
            Console.WriteLine();
            Console.ReadLine();
            }
        }
                 private static string GetConnectionString()
                // To avoid storing the sourceConnection string in your code,  
                // you can retrieve it from a configuration file. 
                {
                    return "Data Source=BESA-PC;" +
                        " Integrated Security = true;" +
                        "Initial Catalog=CykelScore2;";
                }

        }
    }

internal class DistanceCalculator
    {
        public static double GetDistance(string previousCoordinate, string coordinates)
        {
            string[] PairSequence = previousCoordinate.Split(',');

            float sLatitude = float.Parse(PairSequence[0]);
            float sLongitude = float.Parse(PairSequence[1]);

            string[] PairSequence2 = coordinates.Split(',');

            float eLatitude = float.Parse(PairSequence2[0]);
            float eLongitude = float.Parse(PairSequence2[1]);



            var sCoord = new GeoCoordinate(sLatitude, sLongitude);
            var eCoord = new GeoCoordinate(eLatitude, eLongitude);



            return sCoord.GetDistanceTo(eCoord);

        }
    }

    internal class Checkpoint
    {
        public int Id { get; set; }
        public string Coordinates { get; set; }

    }

    internal class Log
    {
        public DateTime TimeStamp { get; set; }
        public int CheckpointId { get; set; }
        public int UserId { get; set; } 

    }

    internal class User
    {
        public int Id { get; set; }
        public string Coordinates { get; set; }
        public string Name { get; set; }

    }

1 个答案:

答案 0 :(得分:4)

上面的代码中存在很多问题。基本上,您正在尝试按照表格的确切模型对类进行建模,但这并不总是最佳路径 例如,我会以这种方式设计你的课程

(为了避免在新类Coordinate和字符串坐标之间命名混淆,我将后者重命名为Location)

internal class Coordinate
{
    public int coordID { get; set; }                // This is your CheckpointID
    public string Location { get; set; }            // This is the string coordinate loaded 
    public DateTime TimeStamp { get; set; }         // This is the TimeStamp of the coordinate
}

internal class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Coordinate> Coordinates {get;set;}
}

有了这些更改,我会以这种方式修改您的查询

@"SELECT User.Id AS UserID, 
        [Log].[TimeStamp],
        [Checkpoints].[Id] as CheckPointID,
        [Checkpoints].[Coordinates] as Location 
  FROM dbo.[Users] INNER JOIN dbo.[Log] 
                        ON [Log].[UserId] = [Users].[Id] 
                   INNER JOIN dbo.[Checkpoints] 
                        ON [Checkpoints].[Id] = [Log].[CheckpointId]
  ORDER BY User.ID, [Log].[TimeStamp]"   <--- This order by is very important

此时你的循环应该随着

改变
User usr = null;
int curUserID = -1;
while (myReader.Read())
{
    int id = Convert.ToInt32(myReader["UserId"]);
    if(curUserID != id)
    {
        // Enter this block only if the user changes from the previous one
        // They are ordered so you are sure to get them in line
        usr = new User()
        {
             Id = id, 
             Name = reader["Name"].ToString(), 
             Coordinates = new List<Coordinate>()
        };
        curUserID = id;
        listOfUsers.Add(usr);
    }

    // Add all the coordinates that belong to the same user
    Coordinate cc = new Coordinate()
    {
        cc.coordID = Convert.ToInt32(reader["CheckPointID"]);
        cc.TimeStamp = Convert.ToDateTime(reader["TimeStamp"]);
        cc.Location = reader["Location"].ToString();
    };
    usr.Coordinates.Add(cc);
}

在此循环结束时,您可以循环listOfUser并使用TimeStamp

命令后,使用属于特定用户的List<Coordinate>计算距离
foreach(User usr in listUser)
{
    ...
    foreach(Coordinate cc in usr.Coordinates.OrderBy(x => x.TimeStamp)
    {
        ......
    }

}

说,我真的建议你花一点时间来学习现代ORM工具(实体框架,Dapper)的使用,它会删除所有从DB加载数据的代码,让你集中精力关于你的任务所需的逻辑。