【问题标题】:Trying to save an entity that has been stored in ASP.NET control state using EntityFramework尝试使用 EntityFramework 保存已存储在 ASP.NET 控件状态中的实体
【发布时间】:2011-12-02 14:45:25
【问题描述】:

这个让我快疯了,尤其是因为我怀疑要么有一个简单的解决方案,要么我对 EF 的要求太高了......

情况是这样的:

我有一个用户控件 (ASCX),它基本上用作 EF 实体的编辑表单。当控件数据绑定时,我通过 ID 从数据库中提取对象并将其置于控件状态(通过覆盖 SaveControlState()LoadControlState())。

然后用户以他们愉快的方式进行任何更改或不进行更改。该对象具有导航属性,因此当他们更改导航属性时,例如通过向对象上的位置集合添加位置,我正在更新处于控制状态的dataItem

最后,在用户完成所有操作并单击保存按钮后,我尝试使用以下代码保存或创建记录:

protected void SaveButton_Click(object sender, EventArgs e)
{
    DepartmentLookup dept = Master.DataContext
        .Departments.Find(ResourceDepartment.SelectedValue.ToInt());

    LocationLookup location = dataItem.Locations[ResourceLocation.SelectedIndex];
    if (dataItem.OfficeLocation == null)
    {
        dataItem.OfficeLocation = new OfficeLocationLookup()
        {
            Location = location,
            OfficeLocationName = location.LocationName
        };
    }
    else if (!dataItem.OfficeLocation.Location.Equals(location))
    {
        dataItem.OfficeLocation.Location = location;
        dataItem.OfficeLocation.OfficeLocationName = location.LocationName;
    }

    foreach (LocationLookup loc in dataItem.Locations)
    {
        if (loc.LocationTypeID == default(int))
        {
            LocationTypeLookup locType = Master.DataContext
                .LocationTypes.SingleOrDefault(lt =>
                    lt.LocationType == loc.LocationType.LocationType);

            if (locType != null)
                loc.LocationType = locType;
        }
        else
        {
            LocationTypeLookup locType = Master.DataContext
                .LocationTypes.Find(loc.LocationTypeID);
            if (locType.LocationType != loc.LocationType.LocationType)
            {
                LocationTypeLookup newType = new LocationTypeLookup()
                {
                    LocationType = loc.LocationType.LocationType
                };

                loc.LocationType = newType;
            }
        }
    }

    dataItem.PrimaryPhone = PrimaryPhone.Text;
    dataItem.CellPhone = CellPhone.Text;
    dataItem.Department = dept;
    dataItem.EmailAddress = EmailAddress.Text;
    dataItem.LastModifiedBy = HttpContext.Current.User.Identity.Name;
    dataItem.LastModifiedDtm = DateTime.UtcNow;

    if (dataItem.ResourceID == default(int))
        Master.DataContext.Resources.Add(dataItem);
    else
    {
        DbEntityEntry<Resource> entry = Master.DataContext.Entry<Resource>(dataItem);
        if (entry != null && entry.State == EntityState.Detached)
        {
            Master.DataContext.Resources.Attach(dataItem);
            // entry.State = EntityState.Modified;
        }
    }

    Master.DataContext.SaveChanges();
}

我尝试了多种不同的方法来尝试将对象保存到数据库中,但都会导致各种错误。唯一没有抛出异常的方法是 SetValues 方法,它也没有保存任何导航属性,因此被证明没有任何价值。

任何帮助或建议都将在此不胜感激,因为我已经为这个问题绞尽脑汁好几天了。

提前致谢! J

【问题讨论】:

    标签: c# asp.net entity-framework


    【解决方案1】:

    在会话中保存实体对象(而不是控制状态)时,我遇到了类似的问题。问题是检索到的对象具有各种不同的 ObjectContext,这导致保存失败。

    这取决于您如何管理上下文,但最好的办法是将上下文与 Request 对象相关联并使用工厂类来检索它,因此您对每个请求使用一个上下文。

    HttpContext.Current.Items["Context"] = context
    

    任何其他模式都给我带来了大问题。

    根据我的经验,将整个实体保存在 Session(或 ControlState)中并不是一个好主意,因为管理上下文很困难。即使使用了上述(非常安全的)模式,上下文也将来自不同的请求。我最终只是将对象 ID 保存到 Session(ControlState) 并使用包装类来检索它们。我在 Request 集合中保留了我想要传递的对象,而不是保留过去回发的任何对象。

    这是我非常悲痛的question,我在类似的领域也有自己的挣扎。希望对你有用。

    【讨论】:

    • 感谢蒂姆,我实施了您的建议,确实解决了许多问题。不幸的是,我仍然有很多似乎与嵌套实体有关的问题。我现在在想,我可能只需要重建我保存方法中的所有实体。您认为这看起来合理吗,还是有更好的方法?
    • @typefragger 我不得不说我重建了实体。如果我正在保存,我会从最低的孩子向上建立实体。我经常一次将它们保存下来。我认为您可以将整个对象图传递给 save 方法,它会为您解决所有问题,但它不会那样工作。您必须在考虑关系的情况下保存实体。我确信这不是最有效的方式,它对我有用
    • @typefragger 附加实体和导航属性也存在问题。对象管理器仅告诉您父对象是否已分离,而不是子对象stackoverflow.com/questions/7938728/…。我也撞到了这个
    • 非常感谢先生,很高兴知道至少我不是愚蠢或疯狂:-)
    • 完全有问题。精神错乱只是一种职业危害。干杯
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 2010-09-14
    • 2016-05-23
    相关资源
    最近更新 更多