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

C# 尝试使用EntityFramework保存已存储在ASP.NET控件状态中的实体,c#,asp.net,entity-framework,C#,Asp.net,Entity Framework,这件事简直让我发疯,特别是因为我怀疑要么有一个简单的解决办法,要么我要求太多的EF 情况是这样的: 我有一个用户控件(ASCX),基本上用作EF实体的编辑表单。当控件数据绑定时,我按ID从数据库中提取对象并将其置于控件状态(通过重写SaveControlState()和LoadControlState()) 然后,用户以自己的方式进行任何更改或其他更改。此对象上有导航属性,因此当它们更改导航属性时,例如通过向对象上的位置集合添加位置,我将更新处于控制状态的dataItem 最后,在用户完成所有操

这件事简直让我发疯,特别是因为我怀疑要么有一个简单的解决办法,要么我要求太多的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();
}
protectedvoid SaveButton\u单击(对象发送方,事件参数e)
{
DepartmentLookup dept=Master.DataContext
.Departments.Find(ResourceDepartment.SelectedValue.ToInt());
LocationLookup location=dataItem.Locations[ResourceLocation.SelectedIndex];
if(dataItem.OfficeLocation==null)
{
dataItem.OfficeLocation=新的OfficeLocationLookup()
{
位置=位置,
OfficeLocationName=location.LocationName
};
}
如果(!dataItem.OfficeLocation.Location.Equals(Location))则为else
{
dataItem.OfficeLocation.Location=位置;
dataItem.OfficeLocation.OfficeLocationName=location.LocationName;
}
foreach(dataItem.Locations中的LocationLookup loc)
{
如果(loc.LocationTypeID==默认值(int))
{
LocationTypeLookup locType=Master.DataContext
.LocationTypes.SingleOrDefault(lt=>
lt.LocationType==loc.LocationType.LocationType);
if(locType!=null)
loc.LocationType=locType;
}
其他的
{
LocationTypeLookup locType=Master.DataContext
.LocationTypes.Find(loc.LocationTypeID);
if(locType.LocationType!=loc.LocationType.LocationType)
{
LocationTypeLookup newType=新LocationTypeLookup()
{
LocationType=loc.LocationType.LocationType
};
loc.LocationType=新类型;
}
}
}
dataItem.PrimaryPhone=PrimaryPhone.Text;
dataItem.mobile=mobile.Text;
dataItem.Department=dept;
dataItem.EmailAddress=EmailAddress.Text;
dataItem.LastModifiedBy=HttpContext.Current.User.Identity.Name;
dataItem.LastModifiedTM=DateTime.UtcNow;
if(dataItem.ResourceID==默认值(int))
Master.DataContext.Resources.Add(dataItem);
其他的
{
DbEntityEntry=Master.DataContext.entry(dataItem);
if(entry!=null&&entry.State==EntityState.Detached)
{
Master.DataContext.Resources.Attach(dataItem);
//entry.State=EntityState.Modified;
}
}
Master.DataContext.SaveChanges();
}
我尝试了许多不同的方法尝试将对象保存到数据库中,所有这些都会导致各种错误。唯一没有引发异常的方法是
SetValues
方法,它也没有保存任何导航属性,因此证明没有任何价值

任何帮助或建议在这里都将非常感谢,因为我已经绞尽脑汁在这个问题上几天了

提前谢谢!
J

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

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

HttpContext.Current.Items["Context"] = context
任何其他模式都会给我带来大问题

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


这是我对自己在类似领域的斗争感到非常悲哀的。希望能有所帮助。

谢谢蒂姆,我实施了你的建议,解决了许多问题。不幸的是,我仍然有很多问题似乎与嵌套实体有关。此时我在想,我可能需要重建save方法上的所有实体。你认为这似乎合理吗,或者有更好的方法吗?@typefragger我不得不说我重建了实体。如果我正在进行保存,我将从最低的子级向上构建实体。我经常一次只保存一个。我以为你可以将一个完整的对象图传递到save方法中,它会为你解决所有问题,但它不是这样工作的。您必须在保存实体时牢记关系。我相信这不是一件好事;这不是最有效的方法me@typefragger附加实体和导航属性也存在问题。objectmanager只会告诉您父对象是否已附加或分离,而不是子对象。我撞上了这一个,太感谢了,先生,很高兴知道至少我不是愚蠢或疯狂的:-)问题。精神错乱只是一种职业危害。干杯