水合物相关的对象

时间:2012-01-05 11:17:16

标签: asp.net-mvc asp.net-mvc-3 entity-framework poco

我正在寻找一种水合相关物体的简单方法。注释属于文档,只有文档的所有者才能添加注释,因此当用户尝试编辑注释时,我需要对相关文档进行水合以找出用户是否可以访问它。在我的服务层中,我有以下内容:

public void editNote(Note note)
    {
        // Get the associated Document object (required for validation) and validate.
        int docID = noteRepository.Find(note.NoteID).DocumentID;
        note.Document = documentRepository.Find(docID);

        IDictionary<string, string> errors = note.validate();
        if (errors.Count > 0)
        {
            throw new ValidationException(errors);
        }

        // Update Repository and save.
        noteRepository.InsertOrUpdate(note);
        noteRepository.Save();
    }

问题是,noteRepository.InsertOrUpdate(注释)抛出一个异常,“ObjectStateManager中已经存在一个具有相同键的对象”。当存储库设置EntityState.Modified时。所以出现了一些问题:

  1. 我是否正确接近这个,如果是这样,我该如何绕过这个例外?
  2. 目前,控制器编辑操作采用NoteCreateEditViewModel。现在这确实有一个DocumentID字段,因为在创建新Note时需要这样做,因为我们需要知道将哪个Document附加到它。但是对于编辑,我不能使用它,因为恶意用户可以提供他们可以访问的DocumentID,从而编辑他们不拥有的Note。那么是否应该有用于创建和编辑的单独视图模型,或者我可以在编辑时以某种方式排除DocumentID?或者是否有更好的方法来查看视图模型,以便不需要ID?
  3. 有没有更好的方法来解决这个问题?我已经读过,我应该将文档存储库作为聚合而丢失Note存储库但不确定是否/如何帮助。
  4. 我问了一个与此相关的类似问题,但不是很清楚,所以希望这个版本能让人理解,从而指出我正确的方向。

    修改

    根据Ladislav Mrnka提供的信息和此处详述的答案:An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key,我的存储库方法似乎需要如下所示:

    public void InsertOrUpdate(Note note)
        {
            if (note.NoteID == default(int)) {
                // New entity
                context.Notes.Add(note);
            } else {
                // Existing entity
                //context.Entry(note).State = EntityState.Modified;
                context.Entry(oldNote).CurrentValues.SetValues(note);
            }
        }
    

    但是如何从上下文中获取oldNote呢?我可以调用context.Entry(Find(note.NoteID))。CurrentValues.SetValues(注释)但是我在这里引入了潜在的问题吗?

1 个答案:

答案 0 :(得分:0)

  

我是否正确接近这个,如果是这样,我该如何解决这个例外?

我想这段代码会从数据库中加载整个Node来查找DocumentID:

int docID = noteRepository.Find(note.NoteID).DocumentID;

在这种情况下,您的InsertOrUpdate无法获取您的节点并将其附加到具有“已修改”状态的上下文,因为您已在上下文中使用相同的键进行注释。常见的解决方案是使用它:

objectContext.NoteSet.ApplyCurrentValues(note);
objectContext.SaveChanges();
  

但是对于编辑,我不能使用它,因为恶意用户可以提供他们有权访问的DocumentID,从而编辑他们不拥有的Note。

在这种情况下,您必须添加一些安全性。您可以将任何数据添加到页面中的隐藏字段中,但客户端不得更改的那些数据必须包含一些额外的安全性。例如,第二个隐藏字段,其中包含在服务器上计算的签名或在服务器上计算的盐值的哈希值。当数据在下一个请求返回到服务器时,它必须重新计算并将签名/哈希与相同的盐进行比较,并验证传递的值和计算值是否相同。当然,客户端必须不知道您用于计算哈希中使用的签名或盐的秘密。

  

我已经读过我应该将文档存储库作为聚合并丢失Note存储库,但不确定是否/如何帮助。

这是使用存储库的更简洁方法,但它无法帮助您解决特定错误,因为您仍需要NoteDocumentId