Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 3 实体框架更新导航实体_Asp.net Mvc 3_Entity Framework_Entity Framework 4.1 - Fatal编程技术网

Asp.net mvc 3 实体框架更新导航实体

Asp.net mvc 3 实体框架更新导航实体,asp.net-mvc-3,entity-framework,entity-framework-4.1,Asp.net Mvc 3,Entity Framework,Entity Framework 4.1,我正在使用EntityFramework4.1开发一个ASP.NETMVC3Web应用程序,但是,我在更新实体的导航实体时遇到了一个问题 我有一个叫做移位的实体 public partial class Shift { public Shift() { this.Locations = new HashSet<ShiftLocation>(); } public int shiftID { get; set; } public

我正在使用EntityFramework4.1开发一个ASP.NETMVC3Web应用程序,但是,我在更新实体的导航实体时遇到了一个问题

我有一个叫做移位的实体

public partial class Shift
{
    public Shift()
    {
        this.Locations = new HashSet<ShiftLocation>();
    }

    public int shiftID { get; set; }
    public string shiftTitle { get; set; }

    public virtual ICollection<ShiftLocation> Locations { get; set; }

}
ShiftService类中的UpdateShift方法如下所示

public partial class ShiftLocation
{
    public int shiftLocationID { get; set; }
    public int shiftID { get; set; }
    public int locationID { get; set; }

    public virtual Shift Shift { get; set; }
}
public void UpdateShift(Shift item)
    {
        _UoW.Shifts.Update(item);
        _UoW.Commit();
    }
然后调用我的通用存储库中的Update方法

public void Update(TEntity entityToUpdate)
    {
        dbSet.Attach(entityToUpdate);
        context.Entry(entityToUpdate).State = EntityState.Modified;
    }
第二次编辑

根据Slauma的回答,我将我的EditShift Post操作编辑为

if (ModelState.IsValid)
            {
                //Shift shift = new Shift();
                Shift shift = _shiftService.GetShiftByID(model.shiftID);
                ShiftLocation shiftLocation = shift.Locations.Where(s => s.shiftID == model.shiftID).Single();

                shift = Mapper.Map<ViewModelShift, Shift>(model);

                shiftLocation.locationID = model.locationID;
                shift.Locations.Add(shiftLocation);

                _shiftService.UpdateShift(shift);

                return RedirectToAction("Index");
            }
现在,我知道为什么会发生这种情况,因为在我的EditPost操作中,我正在检索移位的一个实例,然后在通用存储库中的Update方法中,我尝试附加相同的移位

我现在真的很困惑。我的通用Repositor看起来不错,因为我是从本文顶部提到的MicrosoftMVC教程中复制的


再次感谢您对如何使此简单更新生效的任何帮助。

请参考您的评论

当我到达“编辑班次”后操作时,我想更新“班次” 使用从传入的中检索的新详细信息 “ViewModelShift模型”。此ViewModel还将包含 “locationID”仅用于1“移位位置”,但是,此移位位置 数据库中已经存在,我只想用新的 locationID

。。。我会尝试以下方法(省略您的存储库结构):

shift
的状态设置为
Modified
无效,因为它不会影响任何相关实体。该位置仍将处于状态
未更改
。您还可以将位置的状态设置为
Modified
,但在ViewModel中似乎没有主键属性
shiftLocationID
。因此,找到要更新的正确位置的唯一方法是通过shift的导航属性加载它(
Include
,在上面的示例中)

编辑

第二次编辑中的代码不起作用,因为AutoMapper创建了一个新的
shift
实例,然后将此shift附加到上下文中。但是,由于您已经从数据库中加载了
shift
,因此该
shift
也会附加到上下文中。不能将具有相同键的两个不同实例附加到上下文。这导致了异常

我上面的代码应该可以工作,我尝试使用您的服务和通用存储库重写它。这两者都必须扩展,因为服务和存储库似乎没有足够丰富的功能来执行任务。尤其是通用的
Update
太弱,无法更新对象图(根对象+一个或多个导航属性)

在通用存储库中查找
方法:

public IQueryable<T> Find(Expression<Func<T, bool>> predicate,
    params Expression<Func<T, object>>[] includes)
{
    return dbSet.IncludeMultiple(includes)
        .Where(predicate);
}
// "Flat" means: Scalar and Complex properties, but not Navigation properties
public void UpdateFlatProperties(T attachedEntity, T detachedEntity)
{
    context.Entry(attachedEntity).CurrentValues.SetValues(detachedEntity);
}

能否显示
移位位置
类和
移位服务.UpdateShift(shift)
中的代码?@Slauma-请查看我的编辑。谢谢你。你到底想达到什么目的?假设
shift
存储在数据库中,并且已经在数据库中为其分配了5个
shiftlocation
。现在,您进入
EditShift
post操作。在代码中创建一个
ShiftLocation
对象,并将其添加到
shift.Locations
集合中。您现在是否要:1)将此新位置作为编号6添加到现有位置,或2)是否要删除5个现有位置并将其替换为新位置,或3)是否要将该位置作为5个位置之一(按Id?)进行查找,然后使用新值进行更新?@Slauma-当我到达“EditShift”后期操作时,我想用从传入的“ViewModelShift模型”中检索的新详细信息更新“Shift”。此ViewModel还将仅包含1个“ShiftLocation”的“locationID”,但是,数据库中已经存在此ShiftLocation,我只想用新的locationID更新它。这有意义吗?谢谢。@Slauma-是否需要加载相关的ShiftLocation,即在执行update语句之前附加到Shift?请参阅上面我的第二次编辑。还有什么好主意吗?谢谢。@tgriffiths:您能在第二次编辑时再次检查代码吗?不知何故,这毫无意义:您正在将
shiftLocation
添加到
shift.Locations
集合中,但从之前完全相同的集合中检索了此
shiftLocation
。另外,您实例化了一个新的
位置
,但没有对该实例执行任何操作。我删除了实例化的“位置”,因为它没有执行任何操作。我将“shiftLocation”添加到shift.Locations,因为我的AutoMapper不为我这样做。一旦Mapper.Map代码运行,shift.Locations=0,因此我将使用新更新的“locationID”将shiftLocation添加到shift.Locations。但问题仍然存在,即在执行更新时ObjectStateManager中已经存在密钥。我非常感谢您在这方面所做的工作。你的新编辑看起来不错,我将在我的解决方案中实现它。谢谢
[HttpPost]
public ActionResult EditShift(ViewModelShift model)
{
    if (ModelState.IsValid)
    {
        Shift shift = context.Shifts
            .Include(s => s.Locations)
            .Single(s => s.shiftID == model.shiftID);

        context.Entry(shift).CurrentValues.SetValues(model);

        ShiftLocation location = shift.Locations.Single();
        // because you expect exactly one location

        location.locationID = model.locationID;

        context.SaveChanges();

        return RedirectToAction("Index");
    }

    //...
}
[HttpPost]
public ActionResult EditShift(ViewModelShift model)
{
    if (ModelState.IsValid)
    {
        Shift shift = Mapper.Map<ViewModelShift, Shift>(model);
        _shiftService.UpdateShiftAndLocation(shift, model.LocationID);

        return RedirectToAction("Index");
    }

    //...
}
public void UpdateShiftAndLocation(Shift detachedShift, int locationID)
{
    Shift attachedShift = _UoW.Shifts.Find(
        s => s.ShiftID == detachedShift.ShiftID, s => s.Locations);

    _UoW.Shifts.UpdateFlatProperties(attachedShift, detachedShift);

    ShiftLocation location = attachedShift.Locations.Single();
    // MUST be exactly one location for the Shift in the DB
    // ToDo: Catch the case somehow, if there is no or more than one location
    location.LocationID = locationID;

    _UoW.Commit();
}
public IQueryable<T> Find(Expression<Func<T, bool>> predicate,
    params Expression<Func<T, object>>[] includes)
{
    return dbSet.IncludeMultiple(includes)
        .Where(predicate);
}
// "Flat" means: Scalar and Complex properties, but not Navigation properties
public void UpdateFlatProperties(T attachedEntity, T detachedEntity)
{
    context.Entry(attachedEntity).CurrentValues.SetValues(detachedEntity);
}