【问题标题】:GridView with in-memory data: where to keep objects before they are saved?带有内存数据的 GridView:在保存对象之前将它们保存在哪里?
【发布时间】:2010-01-08 11:06:07
【问题描述】:

我有一个带有 ObjectDataSourceGridView。我想让用户创建几个对象,然后一次性保存它们。

背景:我想为食谱创建一个编辑器。食谱具有基本属性(例如名称和来源),并且具有成分(例如 100 克黄油) 我希望用户设置食谱的所有属性并让他在 (!!) 将其保存到数据库之前定义其成分。还必须可以从列表中删除成分。不能先保存配方,然后再定义成分。

我的问题: 在将成分保存到数据库之前,我应该将它们保存在哪里?

这是我发现的:

  1. ViewState 不是一个选项,因为 ObectDataSource 的 GetData 方法是静态的,因此无法访问视图状态。
  2. 会话不是一个选项,因为用户应该能够同时在同一浏览器的不同选项卡中使用同一页面。
  3. 上下文不是一个选项,因为它无法在回调中存活。
  4. 使用 LinqDataSource 代替 ObectDataSource 不起作用,因为如果数据源不是 linq 数据上下文,它不支持删除操作。
  5. 在 QueryString 中使用唯一 ID(以识别正确的会话对象)是一种解决方法,但它会弄乱 URL。

我已经在网上搜索了一段时间,我尝试了很多东西都没有成功。

非常感谢您的任何帮助和建议!

【问题讨论】:

    标签: asp.net gridview in-memory


    【解决方案1】:

    最好的办法可能是在页面第一次加载时创建一个临时 ID。将其存储在隐藏字段中,以便 viewstate 知道它。

    使用某种自定义类来表示网格的数据。不使用数据源控件,而是使用网格的 DataSource 和 DataMember 属性手动绑定对象。

    使用您生成的临时 ID 作为键将此对象存储在缓存中。

    在每次回发时,更新缓存中的对象并将其重新绑定到网格。

    Viewstate 是通过临时 ID 在客户端上维护身份的机制。 asp.net Cache API 维护服务器上的数据状态。

    【讨论】:

    • 感谢您的帮助。我希望有一种更优雅的方法来解决这个问题......一个带有 ID 的隐藏字段来识别会话对象对我来说有点像另一种解决方法。但是我现在会这样做......也许.Net 4.0会为此提供更好的解决方案。有人知道吗?
    • 我不确定它是否完全可以解决。 “数据源”被设计为数据的“源”,但在您的情况下,源是用户。因此,您将使用数据源作为“数据目的地”。优雅地执行此操作的概念上正确的方法是使用客户端控件,该控件保持其自己的状态,直到它准备好提交给服务器。您可以使用 JQuery 或相关的客户端组件来做到这一点。也有第三方 asp.net 网格使用服务器端控件执行类似操作,但它们在内部的工作方式与我上面描述的非常相似,它们只是抽象了一点。
    【解决方案2】:

    由于似乎没有更优雅的方法来解决这个问题,我将以下代码实现到我的所有 Web 表单都继承的基页面类中:

    /// <summary>
    /// Set an ID to identify the correct session variable (in case there are several ones).
    /// Create this ID when it is needed for the first time.
    /// </summary>
    private string PageCallID
    {
        get
        {
            if (ViewState["PageCallID"] == null) ViewState["PageCallID"] = Guid.NewGuid().ToString("N");
            return ViewState["PageCallID"].ToString();
        }
    }
    
    /// <summary>
    /// Use a hashtable which is stored into the Session to save the in-memory
    /// objects. This helps to keep the viewstate variable at the client small.
    /// </summary>
    protected Hashtable ServerViewState
    {
        get
        {
            string strSessionKey = String.Format("CleverViewState_{0}", PageCallID);
            if (Session[strSessionKey] == null) Session[strSessionKey] = new Hashtable();
            return (Hashtable)Session[strSessionKey];
        }
    }
    

    有了这个,我们可以在任何网络表单上书写:

    ServerViewState["MyDataTable"] = myDataTable;
    

    而不是

    ViewState["MyDataTable"] = myDataTable;
    

    但是,此解决方案不能由静态方法调用。所以我认为这更像是一种解决方法而不是解决方案。

    如果有人知道解决此问题的更好方法,我将不胜感激!

    【讨论】:

      猜你喜欢
      • 2020-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-05
      • 2012-07-07
      • 2013-11-16
      • 2012-03-09
      • 2014-03-30
      相关资源
      最近更新 更多