尝试使用EntityFramework保存已存储在ASP.NET控件状态的实体

时间:2011-12-02 14:45:26

标签: c# asp.net entity-framework

这个让我绝对疯狂,特别是因为我怀疑是否有一个简单的解决方案或者我对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方法,它也没有保存任何导航属性,因此证明没有价值。

任何帮助或建议都会在这里受到高度赞赏,因为我已经对这个问题进行了几天的讨论。

提前致谢! Ĵ

1 个答案:

答案 0 :(得分:1)

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

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

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

任何其他模式都会给我带来很大的问题。

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

这是我非常哀怨的question,我在类似的领域有自己的挣扎。希望它有一些用处。