ASP.. NET MVC实体框架6导航属性没有保存在SaveChanges()库模式在编辑
本文关键字:SaveChanges 存在 编辑 模式 保存 实体 MVC NET 框架 属性 导航 | 更新日期: 2023-09-27 18:05:36
我遇到了一个奇怪的问题,其中导航属性不是在页面的更新上持续存在,而是在创建上。我正在使用实体框架6,ASP通用存储库模式。. NET MVC 5.
框架代码:
我的背景:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("DefaultConnection") { }
}
我的存储库实现:
public class EntityFrameworkRepository : IRepository, IDisposable
{
private ApplicationDbContext _context;
private readonly ConcurrentDictionary<Type, object> _dbSets =
new ConcurrentDictionary<Type, object>();
public EntityFrameworkRepository(ApplicationDbContext context)
{
_context = context;
}
public void Save<T>(T entity) where T : BaseModel
{
GetDbSet<T>().Add(entity);
_context.SaveChanges();
}
public void Update<T> (T entity) where T: BaseModel
{
_context.Entry(entity).State = EntityState.Modified;
_context.SaveChanges();
}
}
这里,Edit页面的Get基础使用AutoMapper在域模型和视图模型之间进行映射。
public ActionResult Edit(int menuId, int? id)
{
MenuItem mi = _repository.Get<MenuItem>((int)id);
Mapper.CreateMap<MenuItem, MenuItemViewModel>();
MenuItemViewModel mivm = Mapper.Map<MenuItem, MenuItemViewModel>(mi);
///....///
}
这个方法不起作用。正如您所看到的,正在通过id检索完整的对象UseSiblingClaim,并将其设置为MenuItem itemToSave。我在_repository.Update()被调用之前检查对象,检查属性是否正确。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int menuId, [Bind(Include = "Id,Name,ControllerName,ActionName,Order,CustomUrl,Tooltip,IconClass,CanUseParentsClaim,DoesNotNeedClaim,UseSiblingClaim_Id")] MenuItemViewModel mivm)
{
if (ModelState.IsValid)
{
mivm.Menu = _repository.Get<Menu>(menuId);
if (mivm.UseSiblingClaim_Id != null)
{
mivm.UseSiblingClaim = _repository.Get<MenuItem>((int)mivm.UseSiblingClaim_Id);
}
MenuItem itemToSave = MapViewModelToModel(mivm, _repository);
_repository.Update<MenuItem>(itemToSave);
return RedirectToAction("Details", "Menu", new { Id = menuId });
}
return View(mivm);
}
下面是MenuItem类:
public class MenuItem : BaseModel
{
public MenuItem()
{
Children = new HashSet<MenuItem>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public virtual MenuItem ParentMenuItem { get; set; }
public virtual Menu Menu { get; set; }
public string Name { get; set; }
///.....///
public virtual MenuItem UseSiblingClaim { get; set; }
}
映射方法在这里:正在设置UseSiblingClaim。
private static MenuItem MapViewModelToModel(MenuItemViewModel mivm, IRepository _repository)
{
MenuItem itemToSave = new MenuItem()
{
UseSiblingClaim = mivm.UseSiblingClaim,
Id = mivm.Id,
ActionName = mivm.ActionName,
CanUseParentsClaim = mivm.CanUseParentsClaim,
ControllerName = mivm.ControllerName,
CustomURL = mivm.CustomURL,
DoesNotNeedClaim = mivm.DoesNotNeedClaim,
IconClass = mivm.IconClass,
Menu = mivm.Menu,
Name = mivm.Name,
Order = mivm.Order,
ParentMenuItem = mivm.ParentMenuItem,
Tooltip = mivm.Tooltip,
};
return itemToSave;
}
这是视图模型:
public class MenuItemViewModel : BaseModel
{
public int Id { get; set; }
public int ParentMenuItem_Id { get; set; }
public MenuItem ParentMenuItem { get; set; }
public int Menu_Id { get; set; }
public Menu Menu { get; set; }
public IEnumerable<SelectListItem> SiblingItems { get; set; }
[DisplayName("Can Use Sibling's Claim")]
public int? UseSiblingClaim_Id { get; set; }
public MenuItem UseSiblingClaim { get; set; }
}
View部分(与Create()和Update()相同):
<div class="form-group">
@Html.LabelFor(model => model.UseSiblingClaim_Id, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(x => x.UseSiblingClaim_Id, Model.SiblingItems, new { @class = "select2", @multiple = "multiple", @style = "width:100%" })
@Html.ValidationMessageFor(model => model.UseSiblingClaim_Id)
</div>
</div>
模型。创建了SiblingItems并将其传递给视图。
为什么不保留UseSiblingClaim导航属性?它适用于创建菜单项,但不是更新?这与我使用通用存储库模式有关吗?请帮助
我找到了一个解决方案。我仍然不确定为什么它没有更新,但我让它工作的方式是在MenuItem对象上显式地公开ForeignKey,如下所示:
public class MenuItem : BaseModel
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// I didn't have this exposed before //
public int? UseSiblingClaim_Id { get; set; }
public virtual MenuItem UseSiblingClaim { get; set; }
}
然后改变我的映射:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MenuItem>()
.HasOptional(x=>x.UseSiblingClaim)
.WithOptionalDependent()
.Map(m => m.MapKey("UseSiblingClaim_Id"));
base.OnModelCreating(modelBuilder);
}
:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MenuItem>()
.HasOptional(x => x.UseSiblingClaim)
.WithMany()
.HasForeignKey(x => x.UseSiblingClaim_Id);
base.OnModelCreating(modelBuilder);
}
然后在我的MenuItemController中,我只需要设置外键属性(UseSiblingClaim_Id),而不是导航属性,这也节省了db之旅。
答案就藏在这里:在实体框架
我遇到了同样的问题。我通过改变
解决了这个问题IEnumerable<Item>
ICollection<Item>