我对C#和ASP.NET(以及一般的编程)都很陌生,并尝试做一些简单的练习。
我想做什么: 我想构建一个简单的MVC应用程序,其中记录将有版本。 那就是:给定一条记录,我即将通过“编辑”-View进行更改,此记录不会被覆盖。而是创建一个新记录(如新版本)。旧记录和新记录都具有相同的ItemId(不是主键!),它们将它们“语义地”链接在一起。为了知道哪个记录是较新的版本,较新的记录的VersionId为旧版本的VersionId的+1。
目前:我已开始致力于创建动作。新记录的VersionId值为1,而ItemId的值为DB加1中的最大ItemId - 除非DB中没有记录,否则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
时,输入名称和提交的值,我收到以下错误:
“转换为值类型'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。
答案 0 :(得分:2)
您的if语句错误:
if (currentMaxItemNr != null)
目前检查currentMaxItemNr
是否有值,如果有,请将其设为1
所以你的陈述应该是if (currentMaxItemNr == null)
修改强>
遗憾的是,我无法复制您的错误,但我确实检查过并发现在空Max()
上调用List
时会抛出异常。所以最好先拨打if (db.ItemWithVersions.Count() > 0)
这样您确定Max()
将返回结果。如果该语句失败,您可以将currentMaxItemNr
设置为0
答案 1 :(得分:1)
可能原因是Id被声明为int(不可为空,因此无法将null赋给id)。
请尝试以下操作。
public int? Id { get; set; }
答案 2 :(得分: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();
答案 3 :(得分:0)
小心试试?
int currentMaxItemNr = db.ItemWithVersions.Max(i => i.ItemNr ?? 1);
如果currentMaxItemNr = 1
null ,则会返回i.ItemNr
。
答案 4 :(得分: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);
}