[英]ASP.NET MVC 5 application - Repository pattern without Entity Framework
[英]ASP.NET MVC Entity Framework 6 Navigation Property not saving on SaveChanges() Repository Pattern on Edit
我遇到一个奇怪的问题,导航属性不存在于页面更新中,而存在于创建中。 我在Entity Framework 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();
}
}
在这里,“获取编辑”页面的基础使用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);
///....///
}
这是行不通的方法。 如您所见,整个对象UseSiblingClaim正在通过id检索,并设置为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; }
}
视图部分(对于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>
创建Model.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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.