【问题标题】:DocumentDB .Net client using connection stringDocumentDB .Net 客户端使用连接字符串
【发布时间】:2019-01-08 18:24:08
【问题描述】:

我检查了 DocumentDB for .Net (here) 上的 MSDN,发现了 3 个有效的构造函数。但是它们都没有使用连接字符串,这对我来说听起来很奇怪。

真的没有办法用连接字符串而不是端点+authKey 组合来实例化客户端,还是我遗漏了什么?

例如,大多数其他 Microsoft 服务都使用此概念,即 https://docs.microsoft.com/en-us/azure/storage/storage-configure-connection-string#parsing-a-connection-string 。 在我们的例子中,如果所有与 Azure 相关的东西都以相同的方式初始化,那就太好了。只是更干净,而不是炫耀。

附: 请停止告诉我有关具有 Uri 和 authKey 参数的现有构造函数,问题(略有)不同。我可以按照我自己提供的链接进行操作,无需帮助。谢谢。

【问题讨论】:

  • 每个构造函数的第一个参数是Uri。那是终点。你要什么连接字符串?
  • @Amy,类似于我可以从 Web 界面获得的内容。 docs.microsoft.com/en-us/azure/documentdb/media/… 来自docs.microsoft.com/en-us/azure/documentdb/…
  • @ADyson,就在突出显示的文本(URI、Keys)下方,有主要和次要连接字符串。
  • 你是说这个构造函数不存在了? this.client = new DocumentClient(new Uri(EndpointUri), PrimaryKey);
  • @Will 我不知道你为什么如此积极无助。我有完全相同的问题,我怀疑大多数从事 Azure 开发的人可能至少有一次想知道。 Microsoft 提供一个组合的 URI + 键“连接字符串”,例如Azure 存储和 Azure DocumentDB,但您只能将其与 Azure 存储 API使用。当其他 API 能够接受它们作为单个参数时,Azure DocumentDB API 要求你提供这两个部分。我认为这是一个完全有效的问题,因为“不,没有办法”的答案令人惊讶,因此很有趣。

标签: c# azure-cosmosdb


【解决方案1】:

你实际上可以通过迂回的方式做到这一点。

internal class CosmosDBConnectionString
{
    public CosmosDBConnectionString(string connectionString)
    {
        // Use this generic builder to parse the connection string
        DbConnectionStringBuilder builder = new DbConnectionStringBuilder
        {
            ConnectionString = connectionString
        };

        if (builder.TryGetValue("AccountKey", out object key))
        {
            AuthKey = key.ToString();
        }

        if (builder.TryGetValue("AccountEndpoint", out object uri))
        {
            ServiceEndpoint = new Uri(uri.ToString());
        }
    }

    public Uri ServiceEndpoint { get; set; }

    public string AuthKey { get; set; }
}

然后

var cosmosDBConnectionString = new CosmosDBConnectionString(connectionString)
var client = new DocumentClient(
            cosmosDBConnectionString.ServiceEndpoint,
            cosmosDBConnectionString.AuthKey)

这取自 Azure WebJobs Extensions SDK,这就是 Azure Functions V2 能够仅使用连接字符串的方式。不必自己尝试解析字符串。

【讨论】:

  • 使用 System.Data.Common;
【解决方案2】:

我创建了一个用于解析连接字符串的类,类似于 CloudStorageAccount.Parse 的工作方式。我试图尽可能地遵循他们的模式,以防他们决定开源它,希望这可以在没有太大变化的情况下做出贡献。

public static class DocumentDbAccount
{
    public static DocumentClient Parse(string connectionString)
    {
        DocumentClient ret;

        if (String.IsNullOrWhiteSpace(connectionString))
        {
            throw new ArgumentException("Connection string cannot be empty.");
        }

        if(ParseImpl(connectionString, out ret, err => { throw new FormatException(err); }))
        {
            return ret;
        }

        throw new ArgumentException($"Connection string was not able to be parsed into a document client.");
    }

    public static bool TryParse(string connectionString, out DocumentClient documentClient)
    {
        if (String.IsNullOrWhiteSpace(connectionString))
        {
            documentClient = null;
            return false;
        }

        try
        {
            return ParseImpl(connectionString, out documentClient, err => { });
        }
        catch (Exception)
        {
            documentClient = null;
            return false;
        }
    }

    private const string AccountEndpointKey = "AccountEndpoint";
    private const string AccountKeyKey = "AccountKey";
    private static readonly HashSet<string> RequireSettings = new HashSet<string>(new [] { AccountEndpointKey, AccountKeyKey }, StringComparer.OrdinalIgnoreCase);

    internal static bool ParseImpl(string connectionString, out DocumentClient documentClient, Action<string> error)
    {
        IDictionary<string, string> settings = ParseStringIntoSettings(connectionString, error);

        if (settings == null)
        {
            documentClient = null;
            return false;
        }

        if (!RequireSettings.IsSubsetOf(settings.Keys))
        {
            documentClient = null;
            return false;
        }

        documentClient = new DocumentClient(new Uri(settings[AccountEndpointKey]), settings[AccountKeyKey]);
        return true;
    }

    /// <summary>
    /// Tokenizes input and stores name value pairs.
    /// </summary>
    /// <param name="connectionString">The string to parse.</param>
    /// <param name="error">Error reporting delegate.</param>
    /// <returns>Tokenized collection.</returns>
    private static IDictionary<string, string> ParseStringIntoSettings(string connectionString, Action<string> error)
    {
        IDictionary<string, string> settings = new Dictionary<string, string>();
        string[] splitted = connectionString.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

        foreach (string nameValue in splitted)
        {
            string[] splittedNameValue = nameValue.Split(new char[] { '=' }, 2);

            if (splittedNameValue.Length != 2)
            {
                error("Settings must be of the form \"name=value\".");
                return null;
            }

            if (settings.ContainsKey(splittedNameValue[0]))
            {
                error(string.Format(CultureInfo.InvariantCulture, "Duplicate setting '{0}' found.", splittedNameValue[0]));
                return null;
            }

            settings.Add(splittedNameValue[0], splittedNameValue[1]);
        }

        return settings;
    }
}

【讨论】:

  • 谢谢!这对我来说已经没有用了,但是上帝,这是解决问题的第一次尝试,而不是把我指向其他构造函数。
  • 没问题。花了 30 分钟研究 CloudStorageAccount 是如何做到的,这也是我想要的!!刚刚卷起袖子:)
【解决方案3】:

DocumentDB SDK 没有使用连接字符串的构造函数重载。它们支持使用端点 + 主密钥和端点 + 权限/资源令牌进行初始化。

如果您想查看单个连接字符串参数,请在此处提议/投票:https://feedback.azure.com/forums/263030-documentdb

【讨论】:

  • 已发布请求,希望得到肯定的答复,因为它不像聚合或其他改变游戏规则的事情那么工作。
  • 我为这个功能投了票。如果可以的话,我会自己贡献它,并且还投票支持开源 SDK。解析连接字符串并通过工厂创建方法(如存储帐户)调用正确的构造函数可能有多难
【解决方案4】:

这对我有用:

    private static DocumentClient InitializeDocumentClient()
    {

        string connectionString = ConfigurationManager.AppSettings["CosmosTest"];
        string[] connectionStringParts = connectionString.Split(';');
        Uri clientUrl = new Uri(connectionStringParts[0].Split('=')[1]);
        int keyStartPosition = connectionStringParts[1].IndexOf('=') + 1;
        string clientKey = connectionStringParts[1].Substring(keyStartPosition, connectionStringParts[1].Length-keyStartPosition);
        return new DocumentClient(clientUrl, clientKey, connectionPolicy);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 2015-02-08
    相关资源
    最近更新 更多