1

我使用由 Visual Studio 生成的服务参考代理的OData服务将文档上传到 SharePoint 2010 和 2013 。ListData.svc执行此任务的代码类似于下面的 C# 片段:

public static void Upload<T>(string libraryName, string localFilePath, string targetLibraryRelativePath, T document)
{
    string fullLibraryPath = ContextFactory.ROOT + LibraryName + targetLibraryRelativePath);
    var ctx = ContextFactory.GetODataContext();
    FileInfo fi = new FileInfo(localFilePath);
    document.Path = fullLibraryPath ;
    document.Name = fi.Name;
    document.ContentType = "Document";
    var mimeType = DeriveMIMEType(localFilePath);
    using (FileStream sourceFile = System.IO.File.Open(localFilePath, FileMode.Open, FileAccess.Read))
    {
        ctx.AddObject(libraryName, document);
        ctx.SetSaveStream(document, sourceFile, true, mimeType, fullLibraryPath + "/" + document.Name);
        ctx.SaveChanges();
    }
}

最近出现了一个新的业务需求:防止文档副本进入库。我想到的第一个方法是引入一个具有强制性唯一值的新列,并在那里放置类似 MD5 哈希的内容:

document.MD5 = CalculateMD5Hash(File.ReadAllBytes(sourceFile));

我希望,如果尝试使用相同的 MD5 哈希进行新上传,该服务必须通过唯一哈希列值约束来防止文档内容重复到达库。

我的期望只是部分正确:虽然服务确实在这种尝试中引发了异常,但重复的内容最终被上传,但缺乏任何原始属性,document从而损害了我的文档库的完整性。

虽然在调用它之前稍微更改实现并检查文档库是否存在相等的 MD5 哈希值并不是问题,SetSaveStream但感觉像是一种过度的努力,完全违背了为 MD5 哈希值列声明唯一约束的目的。

我的问题是:我在这里遗漏了什么吗?有什么方法可以让系统为我执行文档内容唯一性要求,而不会因为将不一致的项目放入文档库而受到惩罚?

4

1 回答 1

1

目前我能想到的最佳选择是:

  1. 在尝试添加文档之前检查库中是否存在 MD5 哈希(正如您在 OP 中已经建议的那样):

    var md5 = GetMd5Hash(File.ReadAllBytes(fi.FullName));
    
    // check that the MD5 hash doesn't exist in the library
    if (ctx.Test.Where(i => i.MD5 == md5).Count() == 0)
    {
        try
        {
            document.Path = fullLibraryPath;
            document.Name = fi.Name;
            document.ContentType = "Document";
            var mimeType = DeriveMIMEType(localFilePath);
            using (FileStream sourceFile = System.IO.File.Open(localFilePath, FileMode.Open, FileAccess.Read))
            {
                ctx.AddObject(libraryName, document);
                ctx.SetSaveStream(document, sourceFile, true, mimeType, fullLibraryPath + "/" + document.Name);
                ctx.SaveChanges();
            }
        }
        catch (DataServiceRequestException)
        {
            // TODO: log the exception
        }
    }
    
  2. 使用try{...}catch{...}语句来捕获异常并删除添加的项目:

    using (FileStream sourceFile = System.IO.File.Open(localFilePath, FileMode.Open, FileAccess.Read))
    {
        ctx.AddObject(libraryName, document);
        ctx.SetSaveStream(document, sourceFile, true, mimeType, fullLibraryPath + "/" + document.Name);
        try
        {
            ctx.SaveChanges();
        }
        catch (Exception)
        {
            _ctx.DeleteObject(document);
            _ctx.SaveChanges();
            // TODO: log the exception
        }
    }
    
于 2013-02-09T00:16:35.933 回答