实体类型上的 属性 是键的一部分,因此无法修改或标记为已修改。 EF 核心 Dotnet 核心
The property on entity type is part of a key and so cannot be modified or marked as modified. EF Core Dotnet Core
过去有人以不同的形式询问过这个问题,但我仍然无法让它工作。
我正在 dotnet core / ef core 中构建一个站点,在一个页面上我想使用 jqGrid 轻松编辑一个 table 将经常更改的页面。 Table被称为CoList(公司列表)
我已经可以添加新行并删除它们,但是当我尝试编辑行时出现此错误:
The property 'AutoId' on entity type 'CoList' is part of a key and so cannot be modified or marked as modified.
我首先创建了数据库,因为它在我开始在这个新网站上工作之前在其他地方使用过。
我的模型CoList.cs:
public partial class CoList
{
public int AutoId { get; set; }
public string CompanyName { get; set; }
public string CoLevel { get; set; }
public string CoCode { get; set; }
}
数据库上下文文件
modelBuilder.Entity<CoList>(entity =>
{
entity.HasKey(e => e.AutoId)
.HasName("PK_CoList");
entity.HasIndex(e => e.AutoId).IsUnique();
entity.Property(e => e.AutoId).HasColumnName("AutoID");
entity.Property(e => e.CoCode)
.IsRequired()
.HasColumnType("varchar(50)");
entity.Property(e => e.CoLevel)
.IsRequired()
.HasColumnType("varchar(50)");
entity.Property(e => e.CompanyName)
.IsRequired()
.HasColumnType("varchar(50)");
});
在编辑控制器中我有:
public string EditCoList(int? Id, [Bind(include: "CompanyName, CoLevel, CoCode")] CoList coList)
{
FPSDemoContext db = _context;
string msg;
try
{
if (ModelState.IsValid)
{
db.Entry(coList).State = EntityState.Modified;
db.SaveChanges();
msg = "Saved";
}
else
{
msg = "Did not validate";
}
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is CoList)
{
var databaseEntity = db.CoList.AsNoTracking().Single(p => p.AutoId == Id);
var databaseEntry = db.Entry(databaseEntity);
foreach (var property in entry.Metadata.GetProperties())
{
var proposedValue = entry.Property(property.Name).CurrentValue;
var originalValue = entry.Property(property.Name).OriginalValue;
var databaseValue = databaseEntry.Property(property.Name).CurrentValue;
entry.Property(property.Name).CurrentValue = proposedValue;
entry.Property(property.Name).OriginalValue = databaseEntry.Property(property.Name).CurrentValue;
}
}
else
{
msg = "Error occured:" + ex.Message;
throw new NotSupportedException("Concurrency conflict " + entry.Metadata.Name);
}
}
// Retry the save operation
db.SaveChanges();
msg = "Saved";
}
return msg;
}
点击保存后,代码在 'Retry Save operation' 上崩溃。
jqGrid代码:
$(function () {
$("#jqGrid").jqGrid({
regional: 'en',
url: "/SiteOptions/GetCoList",
datatype: 'json',
mtype: 'Get',
colNames: ['Id', 'Company Name', 'Company Level', 'Company Code'],
colModel: [
{ key: true, name: 'autoId', index: 'autoId', editable: false },
{ key: false, name: 'companyName', index: 'companyName', editable: true },
{ key: false, name: 'coLevel', index: 'coLevel', editable: true },
{ key: false, name: 'coCode', index: 'coCode', editable: true }],
pager: jQuery('#jqControls'),
rowNum: 10,
rowList: [10, 20, 30, 40, 50],
height: '100%',
viewrecords: true,
caption: 'Company List - Grid',
emptyrecords: 'No Companies to display',
jsonReader: {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: false,
Id: "0"
},
autowidth: true,
multiselect: false
}).navGrid('#jqControls', { edit: true, add: true, del: true, search: false, refresh: true },
{
zIndex: 100,
url: '/SiteOptions/EditCoList',
closeOnEscape: true,
closeAfterEdit: true,
recreateForm: true,
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
},
{
zIndex: 100,
url: "/SiteOptions/CreateCoList",
closeOnEscape: true,
closeAfterAdd: true,
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
},
{
zIndex: 100,
url: "/SiteOptions/DeleteCoList",
closeOnEscape: true,
closeAfterDelete: true,
recreateForm: true,
msg: "Are you sure you want to delete this row? ",
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
});
});
我已经阅读了那些答案,但它们对我没有帮助,或者我误解了什么。
https://github.com/aspnet/EntityFrameworkCore/issues/4560
编辑 #2
根据评论,我将编辑方法更改为:
public async Task<IActionResult> EditCoList(int Id, CoList coList)
{
string msg;
msg = "Model state is not valid";
if (Id != coList.AutoId)
{
msg = "Not Found";
}
if (ModelState.IsValid)
{
try
{
_context.Update(coList);
await _context.SaveChangesAsync();
msg = "Saved";
}
catch (DbUpdateConcurrencyException)
{
if (!CoListExists(coList.AutoId))
{
msg = "Concurrency Exception - Not Found";
}
else
{
msg = "Error";
throw;
}
}
}
return Content(msg);
}
private bool CoListExists(int? id)
{
return _context.CoList.Any(e => e.AutoId == id);
}
我也在使用 viewmodel(有额外的 table 我稍后会需要在那个视图上):
namespace ASPNET_Core_1_0.Models.SiteOptionsViewModels
{
public class SiteOptionsViewModel
{
public IEnumerable<ASPNET_Core_1_0.Models.SiteOptions> SiteOptions { get; set; }
public IEnumerable<ASPNET_Core_1_0.Models.CoList> CoList { get; set; }
public ASPNET_Core_1_0.Models.SiteOptions AutoId { get; set; }
public ASPNET_Core_1_0.Models.SiteOptions CurrentMonth { get; set; }
public ASPNET_Core_1_0.Models.SiteOptions CurrentYear { get; set; }
public ASPNET_Core_1_0.Models.SiteOptions SelectedCompanyId { get; set; }
public ASPNET_Core_1_0.Models.CoList CompanyName { get; set; }
public ASPNET_Core_1_0.Models.CoList CoLevel { get; set; }
public ASPNET_Core_1_0.Models.CoList CoCode { get; set; }
}
}
在控制器中我这样调用视图:
public async Task<IActionResult> Companylist()
{
ViewData["SubTitle"] = "Company List";
ViewData["Message"] = "Edit company list";
var model = new SiteOptionsViewModel
{
SiteOptions = await _context.SiteOptions.ToListAsync(),
CoList = await _context.CoList.ToListAsync()
};
return View(model);
}
我仍然遇到并发错误:
Microsoft.EntityFrameworkCore.DbContext:Error: An exception occurred in the database while saving changes.
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected)
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
有趣的是,当我从 VS 为我的数据库中的任何 table 生成 CRUD 控制器时,它总是有效,在编辑或保存编辑时完全没有问题。我按照生成的代码创建了自己的代码,但仍然出现并发错误。
编辑#3
添加了 prmNames 的 jqGrid js 脚本:{ id: "AutoId" }(根据 Oleg 评论),
$(function () {
$("#jqGrid").jqGrid({
regional: 'en',
prmNames: { id: "AutoId" },
url: "/SiteOptions/GetCoList",
datatype: 'json',
mtype: 'Get',
colNames: ['Id', 'Company Name', 'Company Level', 'Company Code'],
colModel: [
{ key: true, name: 'autoId', index: 'autoId', editable: false },
{ key: false, name: 'companyName', index: 'companyName', editable: true },
{ key: false, name: 'coLevel', index: 'coLevel', editable: true },
{ key: false, name: 'coCode', index: 'coCode', editable: true }],
pager: jQuery('#jqControls'),
rowNum: 10,
rowList: [10, 20, 30, 40, 50],
height: '100%',
viewrecords: true,
caption: 'Company List - Grid',
emptyrecords: 'No Companies to display',
jsonReader: {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: false,
Id: "0"
},
autowidth: true,
multiselect: false
}).navGrid('#jqControls', { edit: true, add: true, del: true, search: false, refresh: true },
{
zIndex: 100,
url: '/SiteOptions/EditCoList',
closeOnEscape: true,
closeAfterEdit: true,
recreateForm: true,
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
},
{
zIndex: 100,
url: "/SiteOptions/CreateCoList",
closeOnEscape: true,
closeAfterAdd: true,
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
},
{
zIndex: 100,
url: "/SiteOptions/DeleteCoList",
closeOnEscape: true,
closeAfterDelete: true,
recreateForm: true,
msg: "Are you sure you want to delete this row? ",
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
});
});
方法(根据 Oleg 评论):
public async Task<IActionResult> EditCoList(CoList coList)
{
string msg;
msg = "Model state is not valid";
/*if (Id != coList.AutoId)
{
msg = "Not Found";
}*/
if (ModelState.IsValid)
{
try
{
_context.Update(coList);
await _context.SaveChangesAsync();
msg = "Saved";
}
catch (DbUpdateConcurrencyException)
{
if (!CoListExists(coList.AutoId))
{
msg = "Concurrency Exception - Not Found";
}
else
{
msg = "Error";
throw;
}
}
}
return Content(msg);
}
还是不开心
有人可以告诉我我做错了什么吗?我还在学习,所以它可能很简单。如果可能的话,你们中的任何人都可以告诉我正确的解决方案吗?
我建议您添加 prmNames: { id: "autoId" }
选项以通知 jqGrid 在发送编辑结果时使用 autoId
属性 而不是 id
属性到服务器。
如果 prmNames
由于某些原因(Guriddo jqGrid 或您的代码中的错误)而无法工作,但您看到 id
属性 具有正确的值被发送到服务器然后您可以将 int id
参数添加到 EditCoList
操作并根据 id
在 行 [=19] 之前分配 coList.AutoId
=]
过去有人以不同的形式询问过这个问题,但我仍然无法让它工作。
我正在 dotnet core / ef core 中构建一个站点,在一个页面上我想使用 jqGrid 轻松编辑一个 table 将经常更改的页面。 Table被称为CoList(公司列表)
我已经可以添加新行并删除它们,但是当我尝试编辑行时出现此错误:
The property 'AutoId' on entity type 'CoList' is part of a key and so cannot be modified or marked as modified.
我首先创建了数据库,因为它在我开始在这个新网站上工作之前在其他地方使用过。
我的模型CoList.cs:
public partial class CoList
{
public int AutoId { get; set; }
public string CompanyName { get; set; }
public string CoLevel { get; set; }
public string CoCode { get; set; }
}
数据库上下文文件
modelBuilder.Entity<CoList>(entity =>
{
entity.HasKey(e => e.AutoId)
.HasName("PK_CoList");
entity.HasIndex(e => e.AutoId).IsUnique();
entity.Property(e => e.AutoId).HasColumnName("AutoID");
entity.Property(e => e.CoCode)
.IsRequired()
.HasColumnType("varchar(50)");
entity.Property(e => e.CoLevel)
.IsRequired()
.HasColumnType("varchar(50)");
entity.Property(e => e.CompanyName)
.IsRequired()
.HasColumnType("varchar(50)");
});
在编辑控制器中我有:
public string EditCoList(int? Id, [Bind(include: "CompanyName, CoLevel, CoCode")] CoList coList)
{
FPSDemoContext db = _context;
string msg;
try
{
if (ModelState.IsValid)
{
db.Entry(coList).State = EntityState.Modified;
db.SaveChanges();
msg = "Saved";
}
else
{
msg = "Did not validate";
}
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is CoList)
{
var databaseEntity = db.CoList.AsNoTracking().Single(p => p.AutoId == Id);
var databaseEntry = db.Entry(databaseEntity);
foreach (var property in entry.Metadata.GetProperties())
{
var proposedValue = entry.Property(property.Name).CurrentValue;
var originalValue = entry.Property(property.Name).OriginalValue;
var databaseValue = databaseEntry.Property(property.Name).CurrentValue;
entry.Property(property.Name).CurrentValue = proposedValue;
entry.Property(property.Name).OriginalValue = databaseEntry.Property(property.Name).CurrentValue;
}
}
else
{
msg = "Error occured:" + ex.Message;
throw new NotSupportedException("Concurrency conflict " + entry.Metadata.Name);
}
}
// Retry the save operation
db.SaveChanges();
msg = "Saved";
}
return msg;
}
点击保存后,代码在 'Retry Save operation' 上崩溃。
jqGrid代码:
$(function () {
$("#jqGrid").jqGrid({
regional: 'en',
url: "/SiteOptions/GetCoList",
datatype: 'json',
mtype: 'Get',
colNames: ['Id', 'Company Name', 'Company Level', 'Company Code'],
colModel: [
{ key: true, name: 'autoId', index: 'autoId', editable: false },
{ key: false, name: 'companyName', index: 'companyName', editable: true },
{ key: false, name: 'coLevel', index: 'coLevel', editable: true },
{ key: false, name: 'coCode', index: 'coCode', editable: true }],
pager: jQuery('#jqControls'),
rowNum: 10,
rowList: [10, 20, 30, 40, 50],
height: '100%',
viewrecords: true,
caption: 'Company List - Grid',
emptyrecords: 'No Companies to display',
jsonReader: {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: false,
Id: "0"
},
autowidth: true,
multiselect: false
}).navGrid('#jqControls', { edit: true, add: true, del: true, search: false, refresh: true },
{
zIndex: 100,
url: '/SiteOptions/EditCoList',
closeOnEscape: true,
closeAfterEdit: true,
recreateForm: true,
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
},
{
zIndex: 100,
url: "/SiteOptions/CreateCoList",
closeOnEscape: true,
closeAfterAdd: true,
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
},
{
zIndex: 100,
url: "/SiteOptions/DeleteCoList",
closeOnEscape: true,
closeAfterDelete: true,
recreateForm: true,
msg: "Are you sure you want to delete this row? ",
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
});
});
我已经阅读了那些答案,但它们对我没有帮助,或者我误解了什么。
https://github.com/aspnet/EntityFrameworkCore/issues/4560
编辑 #2
根据评论,我将编辑方法更改为:
public async Task<IActionResult> EditCoList(int Id, CoList coList)
{
string msg;
msg = "Model state is not valid";
if (Id != coList.AutoId)
{
msg = "Not Found";
}
if (ModelState.IsValid)
{
try
{
_context.Update(coList);
await _context.SaveChangesAsync();
msg = "Saved";
}
catch (DbUpdateConcurrencyException)
{
if (!CoListExists(coList.AutoId))
{
msg = "Concurrency Exception - Not Found";
}
else
{
msg = "Error";
throw;
}
}
}
return Content(msg);
}
private bool CoListExists(int? id)
{
return _context.CoList.Any(e => e.AutoId == id);
}
我也在使用 viewmodel(有额外的 table 我稍后会需要在那个视图上):
namespace ASPNET_Core_1_0.Models.SiteOptionsViewModels
{
public class SiteOptionsViewModel
{
public IEnumerable<ASPNET_Core_1_0.Models.SiteOptions> SiteOptions { get; set; }
public IEnumerable<ASPNET_Core_1_0.Models.CoList> CoList { get; set; }
public ASPNET_Core_1_0.Models.SiteOptions AutoId { get; set; }
public ASPNET_Core_1_0.Models.SiteOptions CurrentMonth { get; set; }
public ASPNET_Core_1_0.Models.SiteOptions CurrentYear { get; set; }
public ASPNET_Core_1_0.Models.SiteOptions SelectedCompanyId { get; set; }
public ASPNET_Core_1_0.Models.CoList CompanyName { get; set; }
public ASPNET_Core_1_0.Models.CoList CoLevel { get; set; }
public ASPNET_Core_1_0.Models.CoList CoCode { get; set; }
}
}
在控制器中我这样调用视图:
public async Task<IActionResult> Companylist()
{
ViewData["SubTitle"] = "Company List";
ViewData["Message"] = "Edit company list";
var model = new SiteOptionsViewModel
{
SiteOptions = await _context.SiteOptions.ToListAsync(),
CoList = await _context.CoList.ToListAsync()
};
return View(model);
}
我仍然遇到并发错误:
Microsoft.EntityFrameworkCore.DbContext:Error: An exception occurred in the database while saving changes. Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions. at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected) at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.d__6.MoveNext() --- End of stack trace from previous location where exception was thrown ---
有趣的是,当我从 VS 为我的数据库中的任何 table 生成 CRUD 控制器时,它总是有效,在编辑或保存编辑时完全没有问题。我按照生成的代码创建了自己的代码,但仍然出现并发错误。
编辑#3
添加了 prmNames 的 jqGrid js 脚本:{ id: "AutoId" }(根据 Oleg 评论),
$(function () {
$("#jqGrid").jqGrid({
regional: 'en',
prmNames: { id: "AutoId" },
url: "/SiteOptions/GetCoList",
datatype: 'json',
mtype: 'Get',
colNames: ['Id', 'Company Name', 'Company Level', 'Company Code'],
colModel: [
{ key: true, name: 'autoId', index: 'autoId', editable: false },
{ key: false, name: 'companyName', index: 'companyName', editable: true },
{ key: false, name: 'coLevel', index: 'coLevel', editable: true },
{ key: false, name: 'coCode', index: 'coCode', editable: true }],
pager: jQuery('#jqControls'),
rowNum: 10,
rowList: [10, 20, 30, 40, 50],
height: '100%',
viewrecords: true,
caption: 'Company List - Grid',
emptyrecords: 'No Companies to display',
jsonReader: {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: false,
Id: "0"
},
autowidth: true,
multiselect: false
}).navGrid('#jqControls', { edit: true, add: true, del: true, search: false, refresh: true },
{
zIndex: 100,
url: '/SiteOptions/EditCoList',
closeOnEscape: true,
closeAfterEdit: true,
recreateForm: true,
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
},
{
zIndex: 100,
url: "/SiteOptions/CreateCoList",
closeOnEscape: true,
closeAfterAdd: true,
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
},
{
zIndex: 100,
url: "/SiteOptions/DeleteCoList",
closeOnEscape: true,
closeAfterDelete: true,
recreateForm: true,
msg: "Are you sure you want to delete this row? ",
afterComplete: function (response) {
if (response.responseText) {
alert(response.responseText);
}
}
});
});
方法(根据 Oleg 评论):
public async Task<IActionResult> EditCoList(CoList coList)
{
string msg;
msg = "Model state is not valid";
/*if (Id != coList.AutoId)
{
msg = "Not Found";
}*/
if (ModelState.IsValid)
{
try
{
_context.Update(coList);
await _context.SaveChangesAsync();
msg = "Saved";
}
catch (DbUpdateConcurrencyException)
{
if (!CoListExists(coList.AutoId))
{
msg = "Concurrency Exception - Not Found";
}
else
{
msg = "Error";
throw;
}
}
}
return Content(msg);
}
还是不开心
有人可以告诉我我做错了什么吗?我还在学习,所以它可能很简单。如果可能的话,你们中的任何人都可以告诉我正确的解决方案吗?
我建议您添加 prmNames: { id: "autoId" }
选项以通知 jqGrid 在发送编辑结果时使用 autoId
属性 而不是 id
属性到服务器。
如果 prmNames
由于某些原因(Guriddo jqGrid 或您的代码中的错误)而无法工作,但您看到 id
属性 具有正确的值被发送到服务器然后您可以将 int id
参数添加到 EditCoList
操作并根据 id
在 行 [=19] 之前分配 coList.AutoId
=]