【问题标题】:ASP.NET MVC Entity Framework 6 Navigation Property not saving on SaveChanges() Repository Pattern on EditASP.NET MVC Entity Framework 6 导航属性未保存在 SaveChanges() 存储库模式上编辑
【发布时间】:2014-05-29 07:19:09
【问题描述】:

我遇到一个奇怪的问题,导航属性不在页面更新上,而是在创建上。 我正在使用 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();
    }
}

这里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);
///....///
}

这是行不通的方法。如您所见,完整对象 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; }
    }

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>

Model.SiblingItems 被创建并传递到视图中。

为什么不保留 UseSiblingClaim 导航属性?它适用于菜单项的创建,但不适用于更新?这与我使用通用存储库模式有关吗?请帮忙

【问题讨论】:

    标签: c# asp.net asp.net-mvc-5 repository-pattern entity-framework-6


    【解决方案1】:

    我找到了解决方案。 我仍然不确定为什么它没有更新,但我让它工作的方式是在 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),而不是导航属性,这也节省了一次数据库之旅。

    答案埋在这里: Cannot get relationship to update for navigation properties in entity framework

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题。我通过更改解决了它

      IEnumerable<Item>
      

      ICollection<Item>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-29
        • 2016-02-12
        • 1970-01-01
        • 1970-01-01
        • 2011-03-09
        • 2015-05-19
        相关资源
        最近更新 更多