我遇到会话问题,我只是获取存储在会话中的数据,我更新了该列表中的一个项目,然后我验证了一些条件。如果满足条件,则只应在会话中更新。
但问题是即使我没有在它反映的会话中更新。
以下是我编写的代码。
int index = (Convert.ToInt32(context.Request["rowIndex"]) - 1);
List<UserOrganizationMapping> updateUserOrgmapping = SessionHelper.GetSessionValue<List<UserOrganizationMapping>>("LstUserOrgMapping");
if (updateUserOrgmapping != null && updateUserOrgmapping.Count > 0)
{
updateUserOrgmapping[index].OrganizationName = context.Request["updateOrganizationName"];
if (context.Request["updateOrganizationVal"] != "Select")
{
updateUserOrgmapping[index].OrganizationId = Convert.ToInt32(context.Request["updateOrganizationVal"]);
}
updateUserOrgmapping[index].ModifiedBy = System.Web.HttpContext.Current.Session["UserID"].ToString();
updateUserOrgmapping[index].StartDate = Convert.ToDateTime(context.Request["updateStartDate"]);
updateUserOrgmapping[index].EndDate = Convert.ToDateTime(context.Request["updateEndDate"]);
string error = VerifyOverlapping(updateUserOrgmapping);
if (error != null)
{
GetSerializable(context, error);
}
else
{
updateUserOrgmapping = SessionHelper.GetSessionValue<List<UserOrganizationMapping>>("LstUserOrgMapping").ToList();
SessionHelper.SetSessionValue("LstUserOrgMapping", updateUserOrgmapping);
}
}
答案 0 :(得分:2)
这是因为执行SessionHelper.GetSessionValue
时得到的是对对象的引用,因此对该对象的所有后续操作都反映在实际数据所在的位置(堆)。这也是为什么SessionHelper.SetSessionValue
的调用在您的情况下是多余的。
您可以通过将您从会话中获取的列表的内容复制到新对象来修复此问题,并对该新实例化的对象执行所有操作:
var updateUserOrmapping = new List<UserOrganizationMapping>(
SessionHelper.GetSessionValue<List<UserOrganizationMapping>>("LstUserOrgMapping")
);
修改强>
正如您所提到的,上述解决方案仍然不够,因为虽然我们对列表本身有了新的引用,但我们通过引用复制的列表项仍然是驻留的列表项在堆上的同一个地方。
基本上,在您的情况下,您需要在发生错误时恢复到目标对象实例(updateUserOrgmapping[index]
)的原始状态。这是一个例子(不是很优雅,但你明白了):
var originalOrganizationName = updateUserOrgmapping[index].OrganizationName;
var originalOrganizationId = updateUserOrgmapping[index].OrganizationId;
var originalModifiedBy = updateUserOrgmapping[index].ModifiedBy;
var originalStartDate = updateUserOrgmapping[index].StartDate;
var originalEndDate = updateUserOrgmapping[index].EndDate;
updateUserOrgmapping[index].OrganizationName = context.Request["updateOrganizationName"];
// ...
string error = VerifyOverlapping(updateUserOrgmapping);
if (error != null)
{
updateUserOrgmapping[index].OrganizationName = originalOrganizationName;
updateUserOrgmapping[index].OrganizationId = originalOrganizationId;
updateUserOrgmapping[index].ModifiedBy = originalModifiedBy;
updateUserOrgmapping[index].StartDate = originalStartDate;
updateUserOrgmapping[index].EndDate = originalEndDate;
GetSerializable(context, error);
}
更优雅的解决方案可能是让UserOrganizationMapping
支持深度复制其状态,然后你可以这样做:
string VerifyOverlapping(IList<UserOrganizationMapping> mappings, UserOrganizationMapping modifiedMapping, int modifiedMappingIndex)
{
string ret = null;
// Keeping the reference to the original mapping.
var originalMapping = mappings[modifiedMappingIndex];
// Temporarily inserting the modified mapping for overlapping check.
mappings[modifiedMappingIndex] = modifiedMapping;
ret = VerifyOverlapping(mappings);
// Getting the original value back on error.
if (ret != null)
mappings[modifiedMappingIndex] = originalMapping;
return ret;
}
// ...
int index = (Convert.ToInt32(context.Request["rowIndex"]) - 1);
var updateUserOrgmapping = SessionHelper.GetSessionValue<List<UserOrganizationMapping>>("LstUserOrgMapping");
if (updateUserOrgmapping != null && updateUserOrgmapping.Count > 0)
{
var mapping = new UserOrganizationMapping(updateUserOrgmapping[index])
{
OrganizationName = context.Request["updateOrganizationName"],
ModifiedBy = System.Web.HttpContext.Current.Session["UserID"].ToString(),
StartDate = Convert.ToDateTime(context.Request["updateStartDate"]),
EndDate = Convert.ToDateTime(context.Request["updateEndDate"])
};
if (context.Request["updateOrganizationVal"] != "Select")
mapping.OrganizationId = Convert.ToInt32(context.Request["updateOrganizationVal"]);
string error = VerifyOverlapping(updateUserOrgmapping, mapping, index);
if (error != null)
GetSerializable(context, error);
// ...
public class UserOrganizationMapping
{
public UserOrganizationMapping() { }
public UserOrganizationMapping(UserOrganizationMapping copyFrom)
{
this.Id = copyFrom.Id;
// Copy all field values
}
}
希望这有帮助。