2016-01-07 3 views
3

Я довольно новичок в C# и ASP.NET (и вообще программировании) и попробую сделать несколько простых упражнений.Получите наибольшее значение из таблицы, если null

Что я пытаюсь сделать: Я хотел бы создать простое приложение MVC, в котором у записей будут версии. То есть: Учитывая запись, которую я собираюсь изменить с помощью «Редактировать» -View, эта запись не будет перезаписана. Вместо этого будет создана новая запись (например, новая версия). Оба, старые и новые записи, имеют тот же ItemId (который не является первичным ключом!), Который связывает их вместе «семантически». Чтобы узнать, какая запись является новой версией, более новая запись имеет VersionId, которая равна +1 версии VersionId более старой.

В настоящее время: Я начал работать над созданием-действием. Новая запись должна получить значение 1, это VERSIONID и ItemId крупнейший Itemid уже в БД плюс 1 - если нет записи в БД и в этом случае ItemId не должно быть 1.

Модель:

namespace HowToUpdate.Models 
{ 
    public class ItemWithVersion 
    { 
     public int Id { get; set; } 
     public int ItemNr { get; set; } 
     public int VersionNr { get; set; } 
     public string Name { get; set; } 
    } 
} 

Действие регулятора:

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create([Bind(Include = "Id,Name")] ItemWithVersion itemWithVersion) 
    { 
     if (ModelState.IsValid) 
     { 
      // set the ItemNr 
      int currentMaxItemNr = db.ItemWithVersions.Max(i => i.ItemNr); 
      itemWithVersion.ItemNr = currentMaxItemNr + 1; 

      // set the VersionNr 
      itemWithVersion.VersionNr = 1; 

      db.ItemWithVersions.Add(itemWithVersion); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 

     return View(itemWithVersion); 
    } 

Проблема: Когда я бегу localhost/ItemWithVersion/Create, е nter a Значение для имени и отправки, я получаю следующую ошибку: «Приведение значения к типу« System.Int32 »не выполнено, потому что материализованное значение равно null. Либо общий параметр типа результата, либо запрос должны использовать тип с нулевым значением. Источник ошибки: int currentMaxItemNr = db.ItemWithVersions.Max(i => i.ItemNr); "

Я пробовал:

// set the ItemNr 
int currentMaxItemNr = db.ItemWithVersions.Max(i => i.ItemNr);   
if (currentMaxItemNr == null) 
{ 
    itemWithVersion.ItemNr = 1; 
} 
else 
{ 
    itemWithVersion.ItemNr = currentMaxItemNr + 1; 
} 

Теперь ошибка, кажется int currentMaxItemNr = db.ItemWithVersions.Max(i => i.ItemNr);

Также int? currentMaxItemNr = db.ItemWithVersions.Max(i => i.ItemNr); и var currentMaxItemNr = db.ItemWithVersions.Max(i => i.ItemNr); не будет никакой пользы

Это, наверное. базовая, но мне нужна ваша помощь! :) Thx.

ответ

1

Перед вызовом метода Max() вам необходимо убедиться, что ваш стол не пуст. Для этого вы можете использовать метод Any().

int currentMaxItemNr = 0; 
if (db.ItemWithVersions.Any()) 
{ 
    currentMaxItemNr = db.ItemWithVersions.Max(i => i.ItemNr); 
} 
itemWithVersion.ItemNr = currentMaxItemNr + 1; 
// set the VersionNr 
itemWithVersion.VersionNr = 1; 

db.ItemWithVersions.Add(itemWithVersion); 
db.SaveChanges(); 
+1

Спасибо! Мне кажется, это лучшее решение. Мне не нужно менять модель, действие остается коротким и понятным. :) – roxxistic

2

Ваш Условный оператор неправильно:

if (currentMaxItemNr != null) в настоящее время проверяет currentMaxItemNr имеет значение, и если он делает, делает его 1

Так что ваше заявление должно быть if (currentMaxItemNr == null)

Edit:

Я не могу воспроизвести вашу ошибку, к сожалению, но я проверил и выяснил, что есть исключение, вызванное при вызове Max() на пустой List. Поэтому было бы лучше сначала позвонить if (db.ItemWithVersions.Count() > 0)

Таким образом, вы уверены, что Max() вернет результат.Если это не соответствует этому утверждению, вы можете установить currentMaxItemNr на 0

+0

thx! Виноват. Но даже тогда я все равно получаю ту же ошибку. :( – roxxistic

+0

Смотрите мои правки :) Надеюсь, это поможет. – Ionicawa

1

Возможно, причина в том, что Id объявлен как int (не имеет значения NULL, поэтому null не может быть присвоен id).
Попробуйте следующее.

public int? Id { get; set; } 
+0

Thx для вашего ответа! Вы решили это! :) Сначала я установил 'public int? ItemId {get; установить;} '. Теперь VisualStudio говорит мне: «Невозможно преобразовать исходный тип« System.Nullable »в целевой тип« int ». Поэтому я изменяю 'int currentMaxItemNr = db.ItemWithVersions.Max (i => i.ItemNr);' to 'int? currentMaxItemNr = db.ItemWithVersions.Max (i => i.ItemNr); '. Теперь это работает! : D – roxxistic

+0

@roxxistic Happy, если это было полезно)) – tchelidze

+0

@roxxistic немного сахара 'int currentMaxItemNr = db.ItemWithVersions.Max (i => i.ItemNr) ?? 1; ' – tchelidze

0

Учимся попробовать?

int currentMaxItemNr = db.ItemWithVersions.Max(i => i.ItemNr ?? 1); 

Это вернет currentMaxItemNr = 1 если ваш i.ItemNr является нулевой.

+0

Thx для вашего ответа! Я пробовал, но complier возвращает ошибку: «Operator» ?? не может применяться к операндам типа «int» и «int». VisualStudio говорит: «Левый операнд« ?? » оператор должен иметь ссылочный или нулевой тип ». – roxxistic

0

вот как я это сделаю. Когда вы нажимаете «Изменить», мы запускаем:

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create([Bind(Include = "Id,Name")] ItemWithVersion itemWithVersion) 
{ 
    if (ModelState.IsValid) 
    { 
     // get the item with highest version 
     ItemWithVersion item = db.ItemWithVersions.Where(i =>i.ItemNr == itemWithVersion.ItemNr).OrderByDescending(i => i.VersionNr).FirstOrDefault(); 
     //if item doesnt exist we need to create 
     if(item == null) { 
      //get the last item with highest ItemNr 
      ItemWithVersion lastitem = db.ItemWithVersions.OrderByDescending(i => i.ItemNr).FirstOrDefault(); 
      if(lastitem == null) { 
      //if we didnt find a item, it means is the first item in the DB 
      itemWithVersion.ItemNr = 1; 
      } else { 
      //increment the itemNr for the new Item 
      itemWithVersion.ItemNr = lastitem.ItemNr + 1; 
      } 
      //set version to 1 since is the first version for this new ItemNr 
      itemWithVersion.VersionNr = 1; 
     } else { 
      //if we found a item for the current ItemNr we increase the version for the new item 
      itemWithVersion.VersionNr = item.VersionNr + 1; 
     } 

     db.ItemWithVersions.Add(itemWithVersion); 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 

    return View(itemWithVersion); 
} 
+0

Thx за ваш ответ! Кажется, это законно, но и больше работы для контроллера/базы данных, если он должен выбрать и заказать из таблицы. Макс мне кажется более эффективным. Однако я не знаю, что на самом деле сделано сервером в этих случаях, и что действительно требует больших усилий. Именно по этой причине я выбрал ответ Шюй. – roxxistic

Смежные вопросы