2013-02-15 3 views
0

Этот метод:асинхронных и анонимные типы

private async Task readFileInfo(string folderId) 

Имеет вызов к другому методу:

importCount = await VM.importVehicles(myXDoc); 

Defined здесь: (примечание: я изменил его от для цикла к для каждого, но я Получают аналогичные результаты).

public async Task<Int32> importVehicles(XDocument importXMLDocument) 
{ 
    var Importedvehicles = from vehicle in importXMLDocument.Descendants("vehicle") 
          select new 
          { 
           VehicleName = vehicle.Element("VehicleName").Value, 
           VehicleYear = vehicle.Element("VehicleYear").Value, 
           Odometer = vehicle.Element("Odometer").Value, 
           LicensePlate = vehicle.Element("LicensePlate").Value, 
           OilWeight = vehicle.Element("OilWeight").Value, 
           OilQuantity = vehicle.Element("OilQuantity").Value, 
           OilFilterModelNumber = vehicle.Element("OilFilterModelNumber"), 
           AirFilterModelNumber = vehicle.Element("AirFilterModelNumber"), 
           OilChangedDate = vehicle.Element("OilChangedDate"), 
           OilChangedOdometer = vehicle.Element("OilChangedOdometer"), 
           NextOilChangeDate = vehicle.Element("NextOilChangeDate"), 
           NextOilChangeOdometer = vehicle.Element("NextOilChangeOdometer"), 
           SettingDistance = vehicle.Element("SettingDistance"), 
           SettingMonths = vehicle.Element("SettingMonths"), 
          }; 

    Int32 vehicleId; 
    vehicleId = await getMaxVehicleId(); 
    try 
    { 

     foreach (var item in Importedvehicles) 
     { 
      vehicle myImportedVehicle = new vehicle(); 
      myImportedVehicle.VehicleId = vehicleId += 1; 
      myImportedVehicle.ImagePath = "Assets/car2.png"; 
      myImportedVehicle.VehicleName = item.VehicleName; 
      myImportedVehicle.VehicleModel = item.VehicleName; 


      myImportedVehicle.VehicleYear = short.Parse(item.VehicleYear); 
      myImportedVehicle.CurrentOdometer = Convert.ToInt32(item.Odometer); 
      myImportedVehicle.LicensePlate = item.LicensePlate; 
      myImportedVehicle.LastOilChangedDate = Convert.ToDateTime(item.OilChangedDate.Value.ToString()).ToString("d"); 
      myImportedVehicle.LastOilChangedOdometer = (Int32)item.OilChangedOdometer; 
      myImportedVehicle.ReminderDistance = (Int32)item.SettingDistance; 
      myImportedVehicle.ReminderMonths = (Int32)item.SettingMonths; 

      vehicleInformation myImportVI = new vehicleInformation(); 
      myImportVI.OilWeight = item.OilWeight; 
      myImportVI.OilAmount = item.OilQuantity; 
      myImportVI.OilFilterNumber = item.OilFilterModelNumber.Value.ToString(); 
      myImportVI.AirFilterNumber = item.AirFilterModelNumber.Value.ToString(); 

      myImportedVehicle.vehicleInfo = myImportVI; 
      m_vehicles.Add(myImportedVehicle); 
     } 
    } 
    catch (Exception ex) 
    { 
     System.Diagnostics.Debug.WriteLine(ex.Message.ToString()); 
    } 

     await SaveList(); 
     return Importedvehicles.Count(); 
    } 

Я получаю сообщение об ошибке:

Object reference not set to an instance of an object.

, когда я ступаю через него iVehicle подсвечивается, но затем он идет прямо к для заявления. Тогда это ошибки, поскольку он выглядит так, как он еще не получил результаты от iVehicle.

+0

где вы на самом деле возвращаете что-нибудь? – BrokenGlass

+1

Я не думаю, что это имеет какое-либо отношение к 'async/await'. Я бы сказал, что из-за ** отложенного исполнения ** в вашем запросе что-то «нулевое». Отлаживайте это первым. –

+0

Опубликовать короткий, но * полный * пример (другие могут компилироваться и запускаться) кода, который показывает проблему. – svick

ответ

1

Это не 100% ответит на ваш вопрос, но это должно дать вам хорошее начало.

Причина, по которой отладчик переходит прямо в for...loop после объявления iVehicle, заключается в том, что ваш запрос не выполняется, когда вы его объявляете. Поэтому iVehicle в этот момент не является коллекцией анонимных типов.

Когда вы вызываете .Count(), запрос выполняется, и iVehicle пытается превратиться в соответствующую коллекцию анонимных типов. Однако, поскольку что-то в запросе (которое выполняется после того, как вы вызываете .Count()), равно null, вы получаете NullReferenceException.

Необходимо знать, что как importXMLDocument, так и возвращаемое значение из запроса Descendants() не имеет значения.

Надеюсь, что это поможет.

EDIT:

Теперь, когда вы дали полный пример, у вас есть кучи мест, которые потенциально могли бы быть null.

Каждый раз, когда вы используете это:

vehicle.Element("SomeElementNameHere") 

Это потенциально может быть null. Затем вы вызываете свойство .Value на объект null.

Вам необходимо убедиться, что каждый элемент определенно существует. Изолируйте каждый случай и определите, какой из них null.

+0

Я проверил как importXMLDocument, так и Desendants возвращают значения. – webdad3

+0

Теперь, когда вы дали правильный пример, вам обязательно нужно убедиться, что каждый элемент существует. Я уточню свой ответ тем, что я имею в виду. –

+0

это было проблемой. – webdad3

1

Попробуйте написать код так:

var query = 
    from vehicle in importXMLDocument.Descendants("vehicle") 
    select new { ... }; 

var iVehicle = query.ToArray(); 

for (var i = 0; i <= iVehicle.Count(); i++) 
{ 
    ... 
} 

Вы должны заставить вычисления запроса. Это то, что делает .ToArray. Сам запрос - это только определение запроса, а не результаты.

+2

Метод расширения 'Count()' заставляет оценивать запрос ... –

+0

Почему бы не вызвать 'ToArray()' cause 'NullReferenceException'? – svick

+0

@SimonWhitehead - Вызов 'Count()' приведет к оценке, но он не зависит от оценки внутри цикла. Итерация последовательности может иметь побочные эффекты, поэтому лучше избегать множественных итераций. – Enigmativity